home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Essentials / MPW 411 / InsideMacintoshHelp < prev    next >
Encoding:
Text File  |  1990-07-19  |  4.7 MB  |  104,452 lines  |  [TEXT/MPS ]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. æKY CopyrightNotice
  2. æC  Copyright Apple Computer, Inc. 1985-1990, All rights reserved.
  3. 411 - Inside Macintosh Help - MPW 3.2 Beta Release.
  4. Wednesday, May 30, 1990 10:06:43 AM
  5.  
  6. Information source: SpInsideMacintosh 1.0 HyperCard stack.
  7.                     Pegasus 1.2.5 Hypercard Stack  IM Vol VI
  8. æKY Help
  9. InsideMacintoshHelp
  10. æC 
  11. AboutInsideMacintoshHelp   Preface                   UserInterfaceGuide        
  12. IntroductiontoSystem7.0    RoadMap                   UserInterfaceGuideVI
  13.                                                      WorldwideSoftwareOverview
  14.                      
  15. AliasManager               HelpManager               ScriptManager              
  16. AppleTalkManager           ListManager               SCSIManager
  17. ColorManager               MemoryManager             ShutdownManager   
  18. ControlManager             MenuManager               SlotManager
  19. DatabaseAccessManager      NotificationManager       SoundManager     
  20. DeferredTaskManager        OSEventManager            StartManager 
  21. DeskManager                PackageManager            TimeManager
  22. DeviceManager              PaletteManager            ToolboxEventManager  
  23. DialogManager              PowerManager              VerticalRetraceManager              
  24. EditionManager             PrintingManager           WindowManager
  25. EventManager               ProcessManagement                 
  26. FileManager                QuickDraw                 
  27. FontManager                ResourceManager           
  28. GraphicsDevicesManager     ScrapManager
  29.  
  30.  
  31. AppleDesktopBus            FloatingPointPackage      SoundDriver                     
  32. BinaryDecimalConversion    GraphicsOverView          StandardFile
  33. ColorPickerPackage         InternationalUtilities    SystemErrorHandler      
  34. ColorQuickDraw             MacintoshHardware         SystemResourceFile
  35. CompatibilityGuidelines    MemoryManagement          TextEdit
  36. ControlPanels              OSUtilities               ToolboxUtilities
  37. DiskDriver                 PPCToolbox                UsingAssemblyLanguage
  38. DiskInitialization         SegmentLoader                
  39. FinderInterface            SerialDrivers                                         
  40.  
  41.  
  42. A.ResultCodes              C.SystemTraps             SystemErrors
  43. B.MovesMemory              D.GlobalVariables         Glossary
  44.  
  45.  
  46.  
  47.  
  48. æKY AboutInsideMacintoshHelp
  49. æC
  50. ------------------------------------------------------------------------------
  51.  Version 1.0 Beta:
  52.  
  53.  Volume VI chapters have been added to this version which contain information
  54.  about System 7.0, new managers and changes to previous ones. 
  55.  
  56.  New manager chapters are:               
  57.     AppleTalk Manager                                             
  58.     DatabaseAccess Manager
  59.     Edition Manager
  60.     Event Manager
  61.     GraphicDevices Manager (Replaces the Graphic Devices chapter in Volume V) 
  62.     Help Manager
  63.     Memory Management
  64.     Power Manager
  65.     PPC Toolbox
  66.     Process Management
  67.  
  68. Changed chapters are:
  69.     Alias Manager 
  70.     Color Picker Package
  71.     Color Quikdraw
  72.     Control Panels
  73.     File Manager
  74.     FinderInterface
  75.     Font Manager
  76.     Notification Manager
  77.     Palette Manager
  78.     Resource Manager
  79.     Slot Manager
  80.     Sound Manager
  81.     TextEdit
  82.     Time Manager
  83.     
  84. New/changed documentation chapters are:
  85.     Compatibility Guidelines
  86.     Graphics Overview
  87.     Introduction to System 7.0
  88.     Preface
  89.     UserInterface Guidelines VI
  90.     Worldwide Software Overview
  91.  
  92. ------------------------------------------------------------------------------
  93.  Version 1.0 Alpha:
  94.  
  95.  InsideMacintoshHelp file provides on-line documentation for the 411 project.
  96.  This version contains all the chapters of InsideMacintosh Volumes I - V.  
  97. æKY AliasManager
  98. æC 
  99. _______________________________________________________________________________
  100.  
  101. ALIAS MANAGER
  102. _______________________________________________________________________________
  103.  
  104. About…the…Alias…Chapter
  105. About…the…Alias…Manager
  106. About…Alias…Records
  107. Strategies…for…Resolving…Alias…Records
  108.     Fast…Search
  109.     Slow…Search
  110. Using…the…Alias…Manager
  111.     Creating…Alias…Records
  112.     Resolving…Alias…Records
  113.     ResolveAlias
  114.     SelectAlias
  115.     MatchAlias
  116.     Reading…Alias…Records
  117.     Maintaining…Alias…Records
  118.     Storing…and…Retrieving…Alias…Records
  119. Alias…Manager…Routines
  120.     Creating…and…Updating…Alias…Records
  121.     Resolving…and…Reading…Records
  122. Summary…of…the…Alias…Manager
  123.     Alias…Constants
  124.     Alias…Data…Types
  125.     Alias…Routines
  126.     Alias…Result…Codes
  127.     Assembly-Language…Information…for…Alias
  128. _______________________________________________________________________________
  129.  
  130.  
  131.  
  132. æKY About…the…Alias…Chapter
  133. æC »ABOUT THIS CHAPTER                                     Alias Manager
  134. _______________________________________________________________________________
  135.  
  136. This chapter describes how your application can use the Alias Manager to
  137. establish and resolve alias records, which are data structures that describe a
  138. file, folder, or volume.
  139.  
  140. You create an alias record to take a fingerprint of an object, usually a file,
  141. that you might need to locate again later. If you store the alias record,
  142. instead of a conventional file specification such as name and parent directory
  143. ID, you can later use the Alias Manager’s algorithms for finding files that have
  144. been moved, renamed, copied, or restored from backup.
  145.  
  146. Note:  The Alias Manager is a utility for exploiting alias records.  It does not
  147.  
  148.        directly manipulate desktop aliases, which are created and managed by the
  149.  
  150.        Finder.  (The Finder Interface chapter describes desktop aliases.)
  151.  
  152. The Alias Manager is available only in system software version 7.0. Call the
  153. Gestalt function, described in the Compatibility Guidelines chapter of this
  154. volume, to determine whether the Alias Manager is present.
  155.  
  156. Read this chapter if you want your application to create and resolve alias
  157. records. You might use an alias record, for example, to identify a customized
  158. dictionary from within a text document. When the user runs a spelling checker on
  159. the document, your application can ask the Alias Manager to resolve the record
  160. to find the correct dictionary.
  161.  
  162. To use this chapter, you should be familiar with the File Manager’s conventions
  163. for identifying files, folders, and volumes, as described in the File Manager
  164. chapters in volume IV and this volume.
  165.  
  166. _______________________________________________________________________________
  167.  
  168. æKY About…the…Alias…Manager
  169. æC »ABOUT THE ALIAS MANAGER                                                  Alias Manager
  170. _______________________________________________________________________________
  171.  
  172. The Alias Manager creates and resolves alias records. The next section, “About
  173. Alias Records,” describes how you can use alias records.
  174.  
  175. In general, you should use the Alias Manager whenever you find yourself storing
  176. specific file or directory information such as full pathname or filename and
  177. parent directory ID. The Alias Manager stores this information and more in the
  178. alias record, and it also provides a set of search strategies for resolving the
  179. record later. The search strategies are described in “Resolving Alias Records,”
  180. later in this chapter.
  181.  
  182. You can use the Alias Manager to
  183.   •   create and resolve alias records
  184.   •   get information from and update alias records
  185.  
  186. The Alias Manager can track files and folders across volumes. If the target of
  187. an alias record is on an unmounted AppleShare® volume, the Alias Manager can
  188. automatically initiate the mounting when it resolves the alias. If the target
  189. object is on an unmounted ejectable disk, the Alias Manager can prompt the user
  190. to insert the disk.
  191.  
  192. When the Alias Manager creates an alias record, it fills in the record and
  193. returns a handle to it. Your application must store and retrieve the records on
  194. disk if necessary. Your application must also supply strategies for handling
  195. various alias-resolution problems, described in “Resolving Alias Records.”
  196.  
  197. To help you understand and use the Alias Manager, this chapter provides
  198.   •   an overview of alias records
  199.   •   a description of how the Alias Manager resolves alias records
  200.   •   specific techniques for using the Alias Manager in your application
  201. _______________________________________________________________________________
  202.  
  203. æKY About…Alias…Records
  204. æC »ABOUT ALIAS RECORDS                                                      Alias Manager
  205. _______________________________________________________________________________
  206.  
  207. An alias record is a data structure that describes a file, folder, or volume.
  208. The record contains a collection of information about its target, including its
  209. name and file ID, creation date, parent directory name and ID, and volume name
  210. and creation date.
  211.  
  212. By storing alias records, you can allow your users to create robust connections
  213. between files—--that is, connections that can survive the moving or renaming of
  214. one or both files. The Finder™ in system software version 7.0 stores an alias
  215. record when the user creates a desktop alias object. The Edition Manager uses
  216. alias records to implement data-sharing among separate documents. (The Finder
  217. Interface and Edition Manager chapters in this volume describe those features in
  218. detail. The section “Using the Alias Manager,” later in this chapter, describes
  219. how the Finder and the Edition Manager call the Alias Manager.)
  220.  
  221. The alias record itself contains two kinds of information: public information
  222. available to your application and private information used by the Alias Manager.
  223.  
  224. TYPE
  225. AliasHandle  =  ^AliasPtr;
  226. AliasPtr     =  ^AliasRecord;
  227. AliasRecord  =
  228.   RECORD
  229.     userType:   OSType;  /* application’s signature */
  230.     aliasSize:  Integer  /* record size when created */
  231.     {variable-length private data}
  232.   END;
  233.  
  234. Your application can use the userType field to store its own signature or any
  235. other data that fits in four bytes. When the Alias Manager fills in an alias
  236. record, it stores four spaces (0x20202020) in that field.
  237.  
  238. The Alias Manager stores the size of the record when it was created in the
  239. aliasSize field. Knowing the starting size allows your application to store and
  240. retrieve data of its own at the end of the record. First, expand the size of the
  241. record with the Memory Manager, described in Volume II. You can then find the
  242. starting address of your own data in the record by adding the record’s starting
  243. address to its original length, as reported in the aliasSize field.
  244.  
  245. The private Alias Manager data includes a collection of file, directory, and
  246. volume names and their creation dates; file and directory IDs; a full pathname,
  247. including the volume name; and, if applicable, AppleShare information for use in
  248. resolving the alias record.
  249.  
  250. When you create an alias record, you have the option of recording a relative
  251. path, that is, the path to the target object from another file or folder on the
  252. same disk. The beginning point of a relative path is called the fromFile. To
  253. record relative path, the Alias Manager saves the distances from the target and
  254. the fromFile to the common parent, that is, the lowest-level directory that
  255. appears in the pathnames of both. The Alias Manager can later use those
  256. distances in conjunction with the absolute pathname to conduct a relative
  257. search.
  258.  
  259. Suppose, for example, that you are writing a word-processing application that
  260. allows the user to build a customized, supplemental dictionary for each
  261. document. You create the dictionary as a separate document in the same folder as
  262. the document it serves, as Figure 24-1 shows.
  263.  
  264. ø 24.1  Recording of Relative Path
  265.  
  266. When resolving the alias record using relative path, the Alias Manager starts at
  267. the directory the specified distance above the fromFile, the directory named
  268. Sample in the example above. The Alias Manager then constructs a pathname by
  269. using one field of the absolute pathname for each step from the target to the
  270. common parent. In this example, the distance is one, so the pathname contains
  271. only the name of the target document, Dictionary.
  272.  
  273. In some circumstances, a relative search identifies the correct target when an
  274. absolute search could not. For example, suppose the user of your word-processing
  275. application creates a working copy of a document and dictionary by copying the
  276. entire folder Sample to another disk. The user later updates the original
  277. document and dictionary by copying the folder from the working disk. All of the
  278. underlying file and folder identifications change, but the filenames and
  279. relative path remain the same. When the user later runs the spelling checker on
  280. the document, a relative-path search finds the target dictionary.
  281.  
  282. The Alias Manager accepts and returns file specifications only in the form of
  283. file system specification records (FSSpec records), described in the File
  284. Manager chapter of this volume. The FSSpec record represents the simlest
  285. complete description of a file system object. It contains a volume reference
  286. number, a parent directory ID, and a name.
  287.  
  288. _______________________________________________________________________________
  289.  
  290. æKY Strategies…for…Resolving…Alias…Records
  291. æC »STRATEGIES FOR RESOLVING ALIAS RECORDS                                   Alias Manager
  292. _______________________________________________________________________________
  293.  
  294. The Alias Manager provides three alias-resolution functions:
  295.  
  296.   •   The high-level function ResolveAlias performs a fast search for a single
  297.       target. If the target resides on an unmounted volume, ResolveAlias
  298.       attempts to mount the volume automatically. If it finds no match for the
  299.       alias record, ResolveAlias simply returns an error code.
  300.  
  301.   •   The high-level function SelectAlias can identify more than one possible
  302.       target. If it identifies either no targets or more than one possible
  303.       target, it displays a dialog box, through which the user can direct the
  304.       search. SelectAlias starts with a fast search and can perform a slow
  305.       search at the user’s request. (Fast and slow searches are described
  306.       below.) If the target resides on an unmounted volume, SelectAlias
  307.       attempts to mount the volume automatically.
  308.  
  309.   •   The low-level function MatchAlias accepts a set of input rules to control
  310.       the search. MatchAlias can perform either a fast or a slow search. It can
  311.       identify and return multiple possible targets. Your program must process
  312.       the results.
  313.  
  314. The following sections describe the fast- and slow-search algorithms the Alias
  315. Manager uses to resolve alias records. For information on using the functions,
  316. see “Using the Alias Manager” and “Alias Manager Routines” later in this
  317. chapter.
  318.  
  319. _______________________________________________________________________________
  320.  
  321. æKY Fast…Search
  322. æC »Fast Search                                                              Alias Manager
  323. _______________________________________________________________________________
  324.  
  325. The fast-search algorithm is designed to find the most likely match for an alias
  326. record first. This strategy meets the needs of the ResolveAlias function, which
  327. exits as soon as it finds one match. The fast-search algorithm can, however,
  328. identify more than one possible target for presentation to the user through the
  329. SelectAlias function.
  330.  
  331. The first step in the search is to identify the volume on which the target
  332. resides, using the volume’s name, creation date (which acts almost as a unique
  333. identifier for a volume), and volume type (for example, a hard disk, a 3.5-inch
  334. disk, or an AppleShare volume).
  335.  
  336. The Alias Manager first looks for a volume by both name and creation date. The
  337. search succeeds if the volume is mounted and if its name and creation date have
  338. not changed since the record was created. If the target is on an unmounted
  339. AppleShare volume, the Alias Manager attempts to mount the volume. If the target
  340. is on an unmounted ejectable disk, the Alias Manager presents the switch-disk
  341. dialog box, illustrated in Figure 24-2.
  342.  
  343. ø 24.2  Switch-Disk Dialog Box
  344.  
  345. If the target volume is not found by name and creation date, the Alias Manager
  346. attempts to match by creation date only. This step locates volumes that have
  347. been renamed. Finally, the Alias Manager attempts to match by volume name only.
  348.  
  349. If none of these strategies results in a volume match, the Alias Manager returns
  350. nvsErr.
  351.  
  352. Once the target volume is identified, fast search looks for the actual target,
  353. first by file ID (if the target is a file) or directory ID (if the target is a
  354. volume or directory). (File IDs are described in the File Manager chapter of
  355. this volume.) Even if a file has been renamed or moved on a volume, the File
  356. Manager can find it quickly through its file ID.
  357.  
  358. If the search by file ID or directory ID fails, fast search looks for the target
  359. by name in the original parent directory. This search locates the target if its
  360. file or directory ID has changed but it still exists by the same name in the
  361. parent directory (for example, if the target was restored from backup). Fast
  362. search compares file numbers on files found by name in the correct parent
  363. directory. If the file numbers do not match, the file is treated as a possible
  364. match, that is, it is put on the list of candidates and the search continues. If
  365. the target is not found by name in the parent directory, fast search looks for a
  366. file by file number in the parent directory.
  367.  
  368. If the search by file ID or directory ID fails, and if fast search cannot find
  369. the original parent directory, it searches for the target by full pathname. This
  370. search finds the target if it resides in the same location on the disk but the
  371. directory ID of its parent directory has changed (for example, if the entire
  372. parent directory was backed up and restored).
  373.  
  374. If the full pathname fails, fast search attempts to find the file by tracing
  375. partial pathnames up through all parent folders, using parent directory IDs
  376. instead of folder names. For example, consider this full pathname:
  377.  
  378. MyDisk:MyReports:January:Sales Report
  379.  
  380. If the search by full pathname fails, fast search first looks for the partial
  381. pathname Sales Report in the directory MyDisk:MyReports:January. If that search
  382. fails, it looks for January:Sales Report in the directory MyDisk:MyReports, and
  383. so on.
  384.  
  385. If the search by absolute pathname fails, and if your application requests a
  386. relative search, fast search performs a relative search. (For a description of
  387. relative path, see “About Alias Records” earlier in this chapter.) The search
  388. succeeds if the relative path is the same as when the record was created and if
  389. the names of the objects have not changed.
  390.  
  391. _______________________________________________________________________________
  392.  
  393. æKY Slow…Search
  394. æC »Slow Search                                                              Alias Manager
  395. _______________________________________________________________________________
  396.  
  397. The slow-search algorithm uses the same strategy as fast search for identifying
  398. the volume.
  399.  
  400. Once the volume is identified, slow search calls the File Manager function
  401. PBCatSearch, searching for objects with a matching creation date, creator, and
  402. type. (See the File Manager chapter for a description of PBCatSearch.) It
  403. searches the entire volume.
  404.  
  405. PBCatSearch is available only on Hierarchical File System (HFS) volumes, not on
  406. Macintosh File System (MFS) volumes. (See the File Manager chapter of this
  407. volume for a description of the two file systems.) PBCatSearch is also available
  408. only on systems running version 7.0 and later. When searching an MFS volume or a
  409. volume on a file server running older system software, slow search performs a
  410. recursive search of the entire volume, searching for objects with matching
  411. creation date, type, creator, or file number.
  412.  
  413. _______________________________________________________________________________
  414.  
  415. æKY Using…the…Alias…Manager
  416. æC »USING THE ALIAS MANAGER                                                  Alias Manager
  417. _______________________________________________________________________________
  418.  
  419. You use the Alias Manager primarily to create and resolve alias records. You can
  420. also use it to look at and update alias records.
  421.  
  422. The Alias Manager creates an alias record in memory and provides you with a
  423. handle to the record. Your application can store the records on disk as
  424. resources of type 'alis' (see “Creating and Updating Alias Records”). When you
  425. no longer need the record in memory, call the DisposHandle procedure, described
  426. in the Memory Manager chapter of Volume II, to free the memory occupied by the
  427. record.
  428.  
  429. All Alias Manager routines accept and return file specifications only in the
  430. form of FSSpec records, which contain a volume reference number, a parent
  431. directory ID, and a target name. Use the File Manager function MakeFSSpec to
  432. convert other forms of file identification, such as pathname, into a canonical
  433. file specification (see the File Manager chapter in this volume for a
  434. description of file identification conventions).
  435.  
  436. For more detailed descriptions of the functions described in this section, see 
  437. “Alias Manager Routines” later in this chapter.
  438.  
  439. _______________________________________________________________________________
  440.  
  441. æKY Creating…Alias…Records
  442. æC »Creating Alias Records                                                   Alias Manager
  443. _______________________________________________________________________________
  444.  
  445. You create a new alias record by calling the NewAlias function. NewAlias fills
  446. in the record and provides a handle to it. NewAlias always records a collection
  447. of information about the target, including the full pathname. You can request
  448. that it store relative path information as well by supplying a starting point
  449. for a relative search.
  450.  
  451. Call NewAlias when you want to store a file description for later use. For
  452. example, suppose you were writing a word-processing application that allows the
  453. user to customize a dictionary for use with a single text file. Your application
  454. stores the custom data in a separate file in the same folder as the document. As
  455. soon as you create the dictionary file, you call NewAlias to create an alias
  456. record for that file, including path information relative to the user’s text
  457. document:
  458.  
  459. MyErr  := NewAlias(textFilePtr, targetPtr, myAliasHdl);
  460.  
  461. The parameter textFilePtr is a pointer to a FSSpec record that identifies the
  462. starting point for the relative search, in this case the user’s text file. If
  463. you do not want relative path information recorded, pass a value of NIL in the
  464. first parameter.
  465.  
  466. The parameter targetPtr is a pointer to a FSSpec record that identifies the
  467. target file, in this example the dictionary file.
  468.  
  469. The parameter myAliasHdl a variable in which the Alias Manager returns a handle
  470. to the target description.
  471.  
  472. _______________________________________________________________________________
  473.  
  474. æKY Resolving…Alias…Records
  475. æC »Resolving Alias Records                                                  Alias Manager
  476. _______________________________________________________________________________
  477.  
  478. The Alias Manager provides three alias-resolution functions:
  479.  
  480.   •   ResolveAlias, which simply searches for one target and exits if it fails
  481.  
  482.   •   SelectAlias, which searches for all plausible targets and displays a
  483.       dialog box to the user if it finds either more than one target or no
  484.       targets
  485.  
  486.   •   MatchAlias, which returns one or more targets
  487.  
  488. ResolveAlias and SelectAlias are both high-level functions, which call the
  489. low-level function MatchAlias. The sections below describe the three functions
  490. in detail. The section “Strategies for Resolving Alias Records,” earlier in this
  491. chapter, describes the underlying search strategies used by the alias-resolution
  492. functions.
  493.  
  494. In general, when you want to identify only the single most likely target of an
  495. alias record, you call ResolveAlias. When you want the user to guide the
  496. resolution of any ambiguous records, you call SelectAlias. When you want your
  497. program to control the search or branch depending on the outcome, you call
  498. MatchAlias.
  499.  
  500. For example, the Finder stores a single alias record for each alias object that
  501. appears on the desktop. When the user opens an alias from the Finder, the Finder
  502. identifies the real object to be opened by resolving the alias record before it
  503. starts up the appropriate application. The Finder calls the ResolveAlias
  504. function, which either finds the target or exits.
  505.  
  506. The Edition Manager follows a more complicated strategy, designed to shield the
  507. user from dialog boxes until they are necessary. Applications can use the
  508. Edition Manager to allow users to incorporate information from one document into
  509. another. When the user inserts shared data into a document, the Edition Manager
  510. stores an alias record that points to the edition, that is, the file that
  511. contains the shared data. Figure 24-3 illustrates how an alias record in a user
  512. document points to an edition.
  513.  
  514. ø 24.3  How the Edition Manager Uses an Alias Record
  515.  
  516. When the user opens a document that includes one or more sections of shared
  517. data, the Edition Manager first checks to see if any of the shared data is out
  518. of date. It then makes a quick attempt to resolve the alias records for all
  519. sections that need to be updated. It calls MatchAlias for each record,
  520. requesting a fast search with automatic mounting suppressed and a maximum of two
  521. matches. If MatchAlias finds only one match for a record, the Edition Manager
  522. accepts that candidate as the correct target. If MatchAlias finds no matches or
  523. two matches, the Edition Manager simply tags that record as unresolved. When the
  524. user tries to display or print a portion of the document that contains an
  525. unresolved record, the Edition Manager calls SelectAlias, which either finder
  526. the target or prompts the user to direct the search for the correct target. This
  527. strategy provides automatic resolution of unambiguous alias records, allows the
  528. user to resolve ambiguities, and delays alias-resolution dialogs until they are
  529. really necessary.
  530.  
  531. _______________________________________________________________________________
  532.  
  533. æKY ResolveAlias
  534. æC »ResolveAlias                                                             Alias Manager
  535. _______________________________________________________________________________
  536.  
  537. In the simplest case, you can call the ResolveAlias function to resolve an alias
  538. record. ResolveAlias performs a fast search (described in “Strategies for
  539. Resolving Alias Records”) and exits after it identifies one target.
  540.  
  541. ResolveAlias compares some key information about the identified target with the
  542. information stored in the alias record. If any of the information is different,
  543. ResolveAlias automatically updates the record.
  544.  
  545. In the dictionary example, illustrated in Figure 24-1, above, the application
  546. calls ResolveAlias when the user runs the spelling-checker on an application
  547. with a customized dictionary.
  548.  
  549. MyErr := ResolveAlias(textFilePtr, myAliasHdl, targetPtr, updateFlag);
  550.  
  551. The parameter textFilePtr is a pointer to a FSSpec record that identifies the
  552. starting point for the relative search, in this case the user’s text file. If
  553. you do not want relative path information used in the search, pass a value of
  554. NIL in the first parameter.
  555.  
  556. The parameter myAliasHdl points to the alias record to be resolved. In this
  557. example, the alias record describes the dictionary file.
  558.  
  559. The parameter targetPtr is a is a pointer to the FSSpec record where the Alias
  560. Manager will place the results of its search. After ResolveAlias completes, the
  561. record pointed to by targetPtr contains the specification for the dictionary
  562. file.
  563.  
  564. The ResolveAlias function uses the updateFlag parameter to report whether or not
  565. it updated the alias record. After ResolveAlias completes, updateFlag is TRUE if
  566. the record was updated and FALSE if it was not.
  567.  
  568. _______________________________________________________________________________
  569.  
  570. æKY SelectAlias
  571. æC »SelectAlias                                                              Alias Manager
  572. _______________________________________________________________________________
  573.  
  574. If you want to let the user handle any ambiguities in the resolution, you can
  575. call the SelectAlias function to resolve an alias.
  576.  
  577. The SelectAlias function always performs a fast search first. If the search
  578. identifies only one target, it behaves exactly like ResolveAlias. If the search
  579. identifies no targets or more than one possible target, the Alias Manager
  580. presents a dialog box like the one in Figure 24-4.
  581.  
  582. ø 24.4  SelectAlias dialog box
  583.  
  584. In this example, the user moved the original target file, Sales Report, to a
  585. different folder. Later, the user copied the file back into its original parent
  586. folder and renamed the original file, now in a different folder, Old Sales
  587. Report. The Sales Report file now appears in the correct parent directory with
  588. the correct name but a different file ID. The file Old Sales Report appears in a
  589. different parent directory with a different name but with the original file ID.
  590. The fast-search algorithm identifies both files as possible targets.
  591.  
  592. The first field in the dialog box informs the user of the ambiguity. The message
  593. is fixed except for the name of the target and the type description, which is
  594. the word immediately before the target name (Edition in this example). You can
  595. control the type description through the fileTypeName parameter in the
  596. SelectAlias function. If you pass an empty string in this parameter, the Alias
  597. Manager substitutes the word document or folder, depending on what kind of
  598. object the alias describes. The name of the target is the original filename
  599. stored in the alias record.
  600.  
  601. The left scroll list, labeled “Name:”, shows the names of all possible alias
  602. matches. The first entry is highlighted when the dialog box first appears.
  603.  
  604. The right scroll list, labeled “Location:”, displays the full path of whatever
  605. entry is highlighted in the Name column. Entries in this list are not
  606. selectable.
  607.  
  608. The Select button accepts the highlighted entry as the target of the alias
  609. record. When the user clicks Select, SelectAlias removes the dialog box and
  610. places the highlighted entry in the target parameter. Pressing the Enter or
  611. Return key or double-clicking an entry in the name list has the same effect as
  612. clicking Select.
  613.  
  614. The Cancel button cancels the entire selection process. When the user clicks
  615. Cancel, SelectAlias removes the dialog box and returns userCanceledErr. Pressing
  616. the Esc (Escape) key or Command-period has the same effect as clicking Cancel.
  617.  
  618. The Try Harder button triggers an asynchronous slow search of all mounted
  619. volumes, beginning, if possible, with the volume on which the target resided
  620. when the alias record was last updated. If the slow search identifies additional
  621. possible matches, the Alias Manager adds them to the name list. If the slow
  622. search takes more than three seconds in real time, the Alias Manager presents a
  623. dialog box that allows the user to cancel the search in progress. Once the Alias
  624. Manager has completed the slow search, it dims the Try Harder button.
  625.  
  626. The Another One button lets the user override the entire selection process. The
  627. Alias Manager presents a dialog box much like the Standard File Package dialog
  628. box, which allows the user to select any file or folder on the system. Clicking
  629. OK accepts the highlighted object as the target of the search. While this dialog
  630. box is on the screen, clicking Cancel returns the user to the SelectAlias dialog
  631. box.
  632.  
  633. In the dictionary example described above, the application could call
  634. SelectAlias instead of ResolveAlias so that the user can help locate the correct
  635. dictionary if a fast search fails to find it.
  636.  
  637. MyErr := SelectAlias(textFilePtr, typeStr, NIL, myAliasHdl, targetPtr,
  638.          updateFlag, NIL, NIL);
  639.  
  640. The parameter textFilePtr is a pointer to a FSSpec record that identifies the
  641. starting point for the relative search, in this case the user’s text file. If
  642. you do not want relative path information used in the search, pass a value of
  643. NIL in the first parameter.
  644.  
  645. The parameter typeStr points to a string containing the word Dictionary. When
  646. SelectAlias displays its dialog box, it uses this string to remind the user that
  647. the target is a dictionary file.
  648.  
  649. The first NIL parameter tells SelectAlias that the application is not supplying
  650. a filter function to process the results of the search.
  651.  
  652. The parameter myAliasHdl points to the alias record to be resolved. In this
  653. example, the alias record describes the dictionary file.
  654.  
  655. The parameter targetPtr is a is a pointer to the FSSpec record where the Alias
  656. Manager will place the results of its search. After SelectAlias completes, the
  657. record pointed to by targetPtr contains the specification for the dictionary
  658. file.
  659.  
  660. The SelectAlias function uses the updateFlag parameter to report whether or not
  661. it updated the alias record. After SelectAlias completes, updateFlag is TRUE if
  662. the record was updated and FALSE if it was not.
  663.  
  664. The second NIL parameter controls the filtering of events by the ModalDialog
  665. procedure while the SelectAlias dialog box is on the screen. A value of NIL
  666. means that your application does no special filtering. (SelectAlias calls
  667. ModalDialog when it displays the SelectAlias dialog box. For a description of
  668. the ModalDialog procedure, see the Dialog Manager chapter of Volume I.) Because
  669. this example does not provide a custom filter function, it does not need to pass
  670. any data of its own, and it sets the final parameter to NIL.
  671.  
  672. _______________________________________________________________________________
  673.  
  674. æKY MatchAlias
  675. æC »MatchAlias                                                               Alias Manager
  676. _______________________________________________________________________________
  677.  
  678. The MatchAlias function is a low-level routine that gives your program control
  679. over the searching algorithm.
  680.  
  681. You can control the search by setting flags in the rulesMask parameter. The
  682. flags let you specify whether to attempt an automatic mounting of unmounted
  683. volumes; whether to search on more than one volume; and whether to perform a
  684. fast search, a slow search, or both. (For details about the rulesMask parameter,
  685. see “Alias Manager Routines” later in this chapter.) You can also specify a
  686. maximum number of candidates to be identified.
  687.  
  688. MatchAlias returns all candidates that it identifies in an array of FSSpec
  689. records.
  690.  
  691. You can use MatchAlias to perform a preliminary search for a target, branching
  692. to different routines depending on the outcome. The Edition Manager calls
  693. MatchAlias, as described in the introduction to this section, “Resolving Alias
  694. Records.”
  695. _______________________________________________________________________________
  696.  
  697. æKY Reading…Alias…Records
  698. æC »Reading Alias Records                                                    Alias Manager
  699. _______________________________________________________________________________
  700.  
  701. To retrieve information from an alias record without actually resolving the
  702. record, call the GetAliasInfo function. You can use GetAliasInfo to retrieve the
  703. name of the target, the names of its parent directories, the name of its volume,
  704. or, in the case of an AppleShare volume, the zone or server name.
  705.  
  706. _______________________________________________________________________________
  707.  
  708. æKY Maintaining…Alias…Records
  709. æC »Maintaining Alias Records                                                Alias Manager
  710. _______________________________________________________________________________
  711.  
  712. To update an alias record, call the UpdateAlias function. You can use
  713. UpdateAlias any time you know that the target of an alias record has been
  714. renamed or otherwise changed.
  715.  
  716. You are most likely to call UpdateAlias after a call to the MatchAlias function.
  717. If MatchAlias identifies a single target, it sets a flag telling you whether or
  718. not the key information about the target file matches the information in the
  719. alias record. It is the responsibility of your application to update the record.
  720.  
  721. The ResolveAlias and SelectAlias functions automatically update an alias record
  722. when the key information about the target they return does not match the record.
  723.  
  724. _______________________________________________________________________________
  725.  
  726. æKY Storing…and…Retrieving…Alias…Records
  727. æC »Storing and Retrieving Alias Records                                     Alias Manager
  728. _______________________________________________________________________________
  729.  
  730. Alias records are stored as resources of type 'alis'.
  731.  
  732. CONST  rAliasType = 'alis'
  733.  
  734. To store and retrieve alias records, use the standard Resource Manager functions
  735. described in the Resource Manager chapter of Volume I.
  736.  
  737. _______________________________________________________________________________
  738.  
  739. æKY Alias…Manager…Routines
  740. æC »ALIAS MANAGER ROUTINES                                                   Alias Manager
  741. _______________________________________________________________________________
  742.  
  743. This section describes the routines you use to create, update, read, and resolve
  744. alias records.
  745.  
  746. All Alias Manager routines use file system specification records (FSSpec
  747. records) to identify files, folders, and volumes. To create a FSSpec record,
  748. call the function MakeFSSpec, described in the File Manager chapter of this
  749. volume.
  750.  
  751. The Alias Manager routines can return the result codes listed in this section or
  752. any other applicable file system or memory management result codes. The file
  753. system result codes are listed in the File Manager chapter of Volume IV, and the
  754. memory management result codes are listed in the Memory Manager chapter of this
  755. volume.
  756.  
  757. _______________________________________________________________________________
  758.  
  759. æKY Creating…and…Updating…Alias…Records
  760. æC »Creating and Updating Alias Records                                      Alias Manager
  761. _______________________________________________________________________________
  762.  
  763. You use the NewAlias function to create an alias record.
  764.  
  765. FUNCTION NewAlias (fromFile,target: FSSpecPtr; VAR alias: AliasHandle) : OSErr;
  766.  
  767. NewAlias creates an alias record that describes the object specified in the
  768. target parameter. It fills in the record and puts a record handle in the alias
  769. parameter.
  770.  
  771. The fromFile parameter represents the starting point for a relative search. This
  772. parameter can be either NIL or a pointer to a valid FSSpec record. If fromFile
  773. is NIL, the alias record does not include relative path information. Specify a
  774. value for fromFile only if you want NewAlias to record relative path
  775. information.
  776.  
  777. The target parameter points to a FSSpec record for the file, folder, or volume
  778. to be described by the alias record.
  779.  
  780. The alias parameter is the handle for the newly created alias record. If the
  781. function fails to create an alias record, it sets alias to NIL.
  782.  
  783. Result codes
  784. paramErr  -50  The target parameter is NIL
  785.  
  786.  
  787. You use the UpdateAlias function to update an alias record.
  788.  
  789. FUNCTION UpdateAlias (fromFile,target: FSSpecPtr; alias: AliasHandle; VAR 
  790.                       wasChanged: Boolean) : OSErr;
  791.  
  792. UpdateAlias updates the alias record pointed to by the alias parameter so that
  793. it describes the file, folder, or volume specified by the target parameter.
  794. UpdateAlias rebuilds the entire alias record.
  795.  
  796. The fromFile parameter represents the starting point for a relative search. This
  797. parameter can be either NIL or a pointer to a valid FSSpec record. If fromFile
  798. is NIL, the updated alias record does not include relative path information.
  799. Specify a value for fromFile only if you want UpdateAlias to record relative
  800. path information.
  801.  
  802. The target parameter is the target of the alias record. This parameter must
  803. point to a valid canonical file specification record.
  804.  
  805. The alias parameter points to the alias record to be updated.
  806.  
  807. If the newly constructed alias record is exactly the same as the old one,
  808. UpdateAlias sets the wasChanged parameter to FALSE. Otherwise, it sets it to
  809. TRUE. Check this parameter to determine whether you need to save an updated
  810. record.
  811.  
  812. Result codes
  813. paramErr  -50  target, alias, or both are NIL, or the handle is corrupt
  814. _______________________________________________________________________________
  815.  
  816. æKY Resolving…and…Reading…Records
  817. æC »Resolving and Reading Records                                            Alias Manager
  818. _______________________________________________________________________________
  819.  
  820. You use the ResolveAlias function to resolve an alias. 
  821.  
  822. FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle; VAR target: 
  823.                        FSSpec; VAR wasChanged: Boolean) : OSErr;
  824.  
  825. If the resolution is successful, ResolveAlias returns the FSSpec record for the
  826. target filename through the target parameter, updates the alias record if
  827. necessary, and reports whether or not the record was updated through the
  828. wasChanged parameter. If the target object is on an unmounted AppleShare volume,
  829. ResolveAlias automatically mounts the volume. If the target is on an unmounted,
  830. ejectable volume, ResolveAlias displays a switch-disk dialog box. ResolveAlias
  831. exits after it finds one acceptable target.
  832.  
  833. The fromFile parameter represents the starting point for a relative search. This
  834. parameter can be either NIL or a valid FSSpec record. If fromFile is NIL,
  835. ResolveAlias does not perform a relative sesarch.
  836.  
  837. The alias parameter points to the alias record to be resolved and, if necessary,
  838. updated.
  839.  
  840. The Target parameter receives the FSSpec record of the target filename.
  841.  
  842. If it updates the alias record, ResolveAlias sets the wasChanged parameter to
  843. TRUE. Otherwise, it sets it to FALSE. If the function returns an error code, it
  844. sets wasChanged to FALSE.
  845.  
  846. Result codes
  847. nsvErr    -35  The volume is not mounted
  848. fnfErr    -43  No target was found
  849. paramErr  -50  The alias parameter is NIL, or the handle is corrupt
  850.  
  851.  
  852. If you want the user to direct the search when an alias record cannot be
  853. resolved unambiguously, call the SelectAlias function.
  854.  
  855. FUNCTION SelectAlias (fromFile: FSSpecPtr; fileTypeName: Str31; aliasFilter: 
  856.                       ProcPtr; alias: AliasHandle; VAR target: FSSpec; VAR 
  857.                       wasChanged: Boolean; filterProc: ProcPtr; callbackPtr:
  858.                       Ptr) : OSErr;
  859.  
  860. If SelectAlias finds a single match for the record pointed to by the alias
  861. parameter, it behaves the same way as ResolveAlias. If SelectAlias finds no
  862. matches or more than one match for the record, the Alias Manager presents a
  863. modal dialog box that allows the user to direct the search and select the
  864. target. (See “User-Directed Search” for a description of the dialog box.)
  865.  
  866. The fromFile parameter represents the starting point for a relative search. This
  867. parameter can be either NIL or a valid FSSpec. If fromFile is NIL, SelectAlias
  868. does not perform a relative search.
  869.  
  870. The fileTypeName string is a descriptive name for the file type of the target
  871. object, intended to help the user select the correct target. It appears as part
  872. of the title of the dialog box.
  873.  
  874. The aliasFilter parameter points to an optional filter function supplied by your
  875. application. The Alias Manager executes this function for each possible match
  876. that SelectAlias finds or after three seconds have elapsed without  a match.
  877. Your filter function returns a Boolean value that determines whether the
  878. possible match is to be discarded (TRUE) or displayed (FALSE). It can also
  879. terminate the search. The function has three parameters.
  880.  
  881.    FUNCTION MySelectAliasFilter (paramBlock: CInfoPBPtr; VAR quitFlag: Boolean; 
  882.                                  callbackPtr: Ptr) : Boolean
  883.  
  884.   The paramBlock parameter points to the catalog information parameter block    
  885.   record (as returned by the File Manager function PBGetCatInfo) of the alias 
  886.   match. The Alias Manager sets this parameter to NIL if it is calling the 
  887.   function to give it the chance to terminate the search. (Do not use this 
  888.   pointer without checking for NIL.) Your filter function sets the quitFlag 
  889.   parameter to terminate the search.
  890.  
  891.   The callbackPtr parameter is the same as the SelectAlias input parameter   
  892.   callbackPtr. This parameter allows your filter function to access your global 
  893.   or local data.
  894.  
  895.  
  896. The alias parameter points to the alias record to be resolved and, if 
  897. necessary, updated.
  898.  
  899. After the alias is resolved to a single target, the target parameter receives
  900. the FSSpec for the target.
  901.  
  902. If it updates the alias record, SelectAlias sets the wasChanged parameter to
  903. TRUE. Otherwise, it sets it to FALSE. If the function returns an error code, it
  904. sets wasChanged to FALSE.
  905.  
  906. The filterProc parameter points to your application’s optional event-filtering
  907. function, to be called by ModalDialog. (SelectAlias calls ModalDialog when it
  908. displays the SelectAlias dialog box. For a description of the ModalDialog
  909. procedure, see the Dialog Manager chapter of Volume I.) The filterProc parameter
  910. is similar to the same parameter in the Standard File Package procedure
  911. SFPGetFile. The function pointed to by filterProc must be the same as the one
  912. you would pass directly to ModalDialog in its filterProc parameter, except that
  913. it takes an additional fourth argument, which is the callbackPtr parameter as
  914. passed to the SelectAlias routine. This option allows your filter function to
  915. access the value of callbackPtr to retrieve your data.
  916.  
  917. The callbackPtr parameter contains whatever data you specify. Use this parameter
  918. to pass information to your filter function.
  919.  
  920. Result codes
  921. fnfErr            -43  No target was found
  922. paramErr          -50  target, alias, or both are NIL, or the handle is corrupt
  923. userCanceledErr  -128  The user canceled the operation
  924.  
  925. You use the MatchAlias function to identify a list of possible matches and pass
  926. the list through a selection filter. The filter can pass more than one possible
  927. match.
  928.  
  929. FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt; alias:
  930. AliasHandle;   
  931.                      VAR aliasCount: Integer; aliasList: FSSpecListPtr; VAR
  932.                      needsUpdate: Boolean; aliasFilter: ProcPtr; callbackPtr:
  933.                      Ptr) : OSErr;
  934.  
  935. MatchAlias resolves the alias record pointed to by the alias parameter and
  936. returns a list of FSSpec records in the structure pointed to by the aliasList
  937. parameter. If it identifies more than one possible target, MatchAlias places in
  938. the aliasCount parameter the number of candidates in aliasList. MatchAlias
  939. follows the rules specified by the rulesMask parameter. If it resolves the alias
  940. to an object other than the one stored in the alias record or if it returns a
  941. list of possible candidates, it sets the needsUpdate flag to TRUE. Your
  942. application is responsible for calling UpdateAlias if necessary after the target
  943. is identified.
  944.  
  945. The fromFile parameter represents the starting point for a relative search. This
  946. parameter can be either NIL or a valid FSSpec record. If fromFile is NIL,
  947. MatchAlias does not perform a relative search.
  948.  
  949. The rulesMask parameter specifies a set of rules to guide the resolution. Pass
  950. the sum of all of the rules you want to invoke.
  951.  
  952. Constant        Description
  953.  
  954. kARMmountVol    Automatically try to mount the target’s volume if it is not    
  955.                 mounted.  If this rule is not set, and if the target’s volume is
  956.  
  957.                 not mounted, MatchAlias returns nsvErr.
  958.  
  959. kARMmultVols    Search all mounted volumes. The search begins with the volume on
  960.  
  961.                 which the target resided when the record was created.
  962.  
  963. kARMsearch      Search quickly for the alias, using the fast-search algorithm.
  964.  
  965. kARMsearchMore  Search further, using the slow-search algorithm.
  966.  
  967.                 The further search uses the File Manager function CatSearch to
  968.                 match criteria such as creation date, type, and creator.
  969.                 CatSearch is available only on HFS volumes. When searching MFS
  970.                 volumes or AppleShare volumes running older system software, 
  971.                 MatchAlias performs a recursive, indexing search using creation 
  972.                 date, type, and creator.
  973.  
  974.                 If both kARMsearch and kARMsearchMore are set, MatchAlias 
  975.                 performs a fast search followed by a slow search.
  976.  
  977. The alias parameter points to the alias record to be resolved.
  978.  
  979. Your application can specify a maximum number of possible matches by setting the
  980. aliasCount parameter. MatchAlias sets the aliasCount parameter to the number of
  981. entries in the list of possible matches.
  982.  
  983. The aliasList parameter points to the array that holds the results of the
  984. search.
  985.  
  986. If MatchAlias resolves the alias to a target whose key information is different,
  987. or if it returns a list of possible candidates, it sets the needsUpdate flag to
  988. TRUE. Otherwise, it sets it to FALSE.
  989.  
  990. The aliasFilter parameter points to a filter function supplied by your
  991. application. The Alias Manager executes this function for each possible match
  992. that MatchAlias finds or after three seconds have elapsed without  a match. Your
  993. filter function returns a Boolean value that determines whether the possible
  994. match is discarded (TRUE) or added to the list of possible targets (FALSE). It
  995. can also terminate the search. The function has three parameters.
  996.  
  997.    FUNCTION MyMatchAliasFilter (paramBlock: CInfoPBPtr; VAR quitFlag: Boolean;  
  998.                                 callbackPtr: Ptr): Boolean
  999.    The paramBlock parameter points to the catalog information parameter block  
  1000.  
  1001.    record (as returned by the File Manager function PBGetCatInfo) of the alias 
  1002.    match. The Alias Manager sets this parameter to NIL if it is calling the 
  1003.    function to give it the chance to terminate the search. (Do not use this 
  1004.    pointer without checking for NIL.) Your filter function sets the quitFlag 
  1005.    parameter to terminate the search.
  1006.  
  1007.    The callbackPtr parameter is the same as the MatchAlias input parameter   
  1008.    callbackPtr. This parameter allows your filter function to access your global
  1009.  
  1010.    or local data.
  1011.  
  1012.  
  1013.    The callbackPtr parameter contains whatever data you specify. Use this 
  1014.    parameter to pass information to your filter function.
  1015.  
  1016. Result codes
  1017. nsvErr            -35  The volume is not mounted
  1018. fnfErr            -43  No target was found
  1019. paramErr          -50  target, alias, or both are NIL, or the handle is corrupt
  1020. userCanceledErr  -128  The user canceled the operation
  1021.  
  1022.  
  1023. You can use the GetAliasInfo function to read information from an alias record.
  1024.  
  1025. FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType; VAR theString:
  1026.                        Str63 ) : OSErr;
  1027.  
  1028. GetAliasInfo retrieves the information specified by the index parameter from the
  1029. record pointed to by the alias parameter and places it in the parameter
  1030. theString.
  1031.  
  1032. The alias parameter points to the alias record to be read.
  1033.  
  1034. The index parameter specifies the kind of information to be retrieved. If index
  1035. is a positive integer, GetAliasInfo retrieves the parent folder that has the
  1036. same hierarchical level as the index parameter. You can therefore assemble the
  1037. names of the target and all of its parent folders by making repeated calls to
  1038. GetAliasInfo with incrementing index values, starting with a value of 0. When
  1039. index is greater than the hierarchical level of the root, GetAliasInfo returns
  1040. an empty string. You can also set index to one of these five values:
  1041.  
  1042. Constant      Value  Description
  1043. asiZoneName    -3    If the record represents an object on an AppleShare volume,
  1044.  
  1045.                      retrieve the server’s zone name. Otherwise, return an empty
  1046.                      string.
  1047.  
  1048. asiServerName  -2    If the record represents an object on an AppleShare volume,
  1049.  
  1050.                      retrieve server name. Otherwise, return an empty string.
  1051.  
  1052. asiVolumeName  -1    Return the name of the volume on which the represented 
  1053.                      object resides.
  1054.  
  1055. asiAliasName    0    Return the name of the object represented by the record.
  1056.  
  1057. asiParentName   1    Return the name of the parent folder of the object 
  1058.                      represented by the record. If the object is a volume, 
  1059.                      return the volume name.
  1060.  
  1061. GetAliasInfo places the requested information in the parameter theString.
  1062.  
  1063. GetAliasInfo returns the information stored in the alias record, which might not
  1064. be current.
  1065.  
  1066. Result codes
  1067. paramErr  -50  alias, theString, or both are NIL; the index is less
  1068.                than asiZoneName; or the handle is corrupt
  1069. _______________________________________________________________________________
  1070.  
  1071. æKY Summary…of…the…Alias…Manager
  1072. æC »SUMMARY OF THE ALIAS MANAGER                                             Alias Manager
  1073. _______________________________________________________________________________
  1074.  
  1075. The following cards summarize the constants, data types, and routines for the
  1076. Alias Manager.
  1077. _______________________________________________________________________________
  1078.  
  1079. æKY Alias…Constants
  1080. æC »Constants                                                           Alias Manager
  1081. _______________________________________________________________________________
  1082.  
  1083. CONST
  1084. rAliasType  =  'alis';    {resource type for saved alias records}
  1085.  
  1086. {rulesMask for MatchAlias}
  1087. kARMmountVol    =  $0001;  {mount the volume automatically}
  1088. kARMmultVols    =  $0008;  {search on multiple volumes}
  1089. kARMsearch      =  $0100;  {search quickly}
  1090. kARMsearchMore  =  $0200;  {search further}
  1091.  
  1092. {index values for GetAliasInfo}
  1093. asiZoneName    =  -3;
  1094. asiServerName  =  -2;
  1095. asiVolumeName  =  -1;
  1096. asiAliasName   =   0;
  1097. asiParentName  =   1;
  1098. _______________________________________________________________________________
  1099.  
  1100. æKY Alias…Data…Types
  1101. æC »Data Types                                                               Alias Manager
  1102. _______________________________________________________________________________
  1103.  
  1104. TYPE
  1105. FSSpecArrayPtr  =  ^FSSpecArray;
  1106. FSSpecArray     =  ARRAY[0..0] OF FSSpec;
  1107.  
  1108. AliasHandle    =  ^AliasPtr;
  1109. AliasPtr       =  ^AliasRecord;
  1110. AliasRecord    =
  1111.   RECORD
  1112.     userType:  OSType;
  1113.     aliasSize:  Integer;
  1114.     {variable-length private data}
  1115.   END;
  1116. AliasInfoType  =  Integer;
  1117. _______________________________________________________________________________
  1118.  
  1119. æKY Alias…Routines
  1120. æC »Routines                                                                 Alias Manager
  1121. _______________________________________________________________________________
  1122.  
  1123. Creating and Updating Records
  1124.  
  1125. FUNCTION NewAlias (fromFile,target: FSSpecPtr; VAR alias: AliasHandle) : OSErr;
  1126. FUNCTION UpdateAlias (fromFile,target: FSSpecPtr; alias: AliasHandle; VAR 
  1127.                       wasChanged: Boolean) : OSErr;
  1128.  
  1129. Resolving and Reading Records
  1130.  
  1131. FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle; VAR target: 
  1132.                        FSSpec; VAR wasChanged: Boolean) : OSErr;
  1133. FUNCTION SelectAlias (fromFile: FSSpecPtr; fileTypeName: Str31; aliasFilter: 
  1134.                       ProcPtr; alias: AliasHandle; VAR target: FSSpec; VAR 
  1135.                       wasChanged: Boolean; filterProc: ProcPtr; callbackPtr:
  1136.                       Ptr) 
  1137.                       : OSErr;
  1138. FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt; alias:
  1139. AliasHandle; 
  1140.                      VAR aliasCount: Integer; aliasList: FSSpecListPtr; VAR 
  1141.                      needsUpdate: Boolean; aliasFilter: ProcPtr; callbackPtr: 
  1142.                      Ptr) : OSErr;
  1143. FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType; VAR theString: 
  1144.                        Str63; ) : OSErr;
  1145. _______________________________________________________________________________
  1146.  
  1147. æKY Alias…Result…Codes
  1148. æC »Result Codes                                                             Alias Manager
  1149. _______________________________________________________________________________
  1150.  
  1151. nsvErr            -35  The volume is not mounted
  1152. fnfErr            -43  No target was found
  1153. paramErr          -50  One or more parameters is NIL, or a handle is corrupt
  1154. userCanceledErr  -128  The user canceled the operation
  1155. _______________________________________________________________________________
  1156.  
  1157. æKY Assembly-Language…Information…for…Alias
  1158. æC »Assembly-Language Information                                            Alias Manager
  1159. _______________________________________________________________________________
  1160.  
  1161. Constants
  1162.  
  1163. ;Resource type for alias records
  1164. rAliasType  .EQU  'alis'
  1165.  
  1166. ;rulesMask for MatchAlias
  1167. kARMmountVol    .EQU  $00000001;  {mount the volume automatically}
  1168. kARMmultVols    .EQU  $00000008;  {search on multiple volumes}
  1169. kARMsearch      .EQU  $00000100;  {search quickly}
  1170. kARMsearchMore  .EQU  $00000200;  {search further}
  1171.  
  1172. ;GetAliasInfo request types
  1173. asiZoneName    .EQU  -3  ;get zone name
  1174. asiServerName  .EQU  -2  ;get server name
  1175. asiVolumeName  .EQU  -1  ;get volume name
  1176. asiAliasName   .EQU   0  ;get object name
  1177. asiParentName  .EQU   1  ;get parent folder name
  1178.  
  1179. Alias Record Data Structure
  1180. userType               4 bytes      file type of target file
  1181. aliasSize              2 bytes      size of record in bytes
  1182. {variable-length private data}
  1183.  
  1184.  
  1185. _______________________________________________________________________________
  1186.  
  1187.  
  1188. æKY AppleDesktopBus
  1189. æC 
  1190. THE APPLE DESKTOP BUS
  1191. _______________________________________________________________________________
  1192.  
  1193. About…The…AppleDesktopBus…Chapter
  1194. About…the…Apple…Desktop…Bus
  1195. ADB…Manager…Routines
  1196. Writing…ADB…Device…Drivers
  1197. Summary…of…the…ADB
  1198. _______________________________________________________________________________
  1199.  
  1200.  
  1201.  
  1202. æKY About…The…AppleDesktopBus…Chapter
  1203. æC »ABOUT THIS CHAPTER                                        AppleDesktopBus
  1204. _______________________________________________________________________________
  1205.  
  1206. This chapter tells you how to accomplish low-level communication with peripheral
  1207. devices that are connected to the Apple Desktop Bus (ADB).
  1208.  
  1209. Reader’s guide:    The standard mouse and keyboard drivers automatically take
  1210.                    care of all required ADB access functions. When the user
  1211.                    manipulates the mouse or keyboard, the system calls the
  1212.                    appropriate driver and the application never uses the ADB
  1213.                    Manager. Hence you need the information in this chapter only
  1214.                    if you are writing a special driver, such as a driver for a
  1215.                    new user-input device.
  1216.  
  1217. The ADB is a simple local-area network that connects low-speed input-only devices to
  1218. the operating system. In the Macintosh II and Macintosh SE computers, the ADB is used
  1219. to communicate with one or more keyboards, the mouse, and other user input devices.
  1220.  
  1221. Keys located on multiple keyboards are distinguished by the keyboard event message,
  1222. as described in the Toolbox Event Manager chapter.
  1223.  
  1224. Note:  An ADB, using the same operating protocols, is also part of the
  1225.        Apple IIgs computer.
  1226.  
  1227. This chapter contains three principal sections:
  1228.  
  1229.   •  a description of the Apple Desktop Bus and how it works
  1230.   •  a description of the ADB Manager. This section of system ROM contains
  1231.      the routines that a driver must use to access devices connected to the ADB.
  1232.   •  a discussion of the special requirements for drivers that support
  1233.      devices connected to the ADB
  1234.  
  1235. You should already be familiar with
  1236.  
  1237.   •  the hardware interface to the Apple Desktop Bus, described in the
  1238.      Macintosh Family Hardware Reference
  1239.   •  events generated by ADB keyboard devices (described in the Toolbox
  1240.      Event Manager chapter) if your driver communicates with one or more
  1241.      keyboards
  1242.  
  1243. _______________________________________________________________________________
  1244.  
  1245.  
  1246. æKY About…the…Apple…Desktop…Bus
  1247. æC »ABOUT THE APPLE DESKTOP BUS                               AppleDesktopBus
  1248. _______________________________________________________________________________
  1249.  
  1250. The Apple Desktop Bus connects up to 16 low-speed input-only devices to the Macintosh
  1251. II or Macintosh SE computer. Each device can maintain up to four variable-size registers,
  1252. whose contents can be read from or written to by the ADB network. Each register may
  1253. contain from two to eight bytes. Two of the device registers have an assigned meaning
  1254. and a standardized format: register 0, used for interrupt information, and register
  1255. 3, containing the device’s identification number. The other two device registers have
  1256. no assigned meaning, and may have different meanings for read and write operations.
  1257.  
  1258. The system communicates with the Apple Desktop Bus through the system’s Versatile
  1259. Interface Adapter chip (VIA). The VIA is described in the Macintosh Hardware chapter.
  1260.  
  1261. Warning:  The ADB does not support connecting a device while the computer
  1262.           is running. The result may be to reinitialize all devices on the
  1263.           bus without informing the system.
  1264.  
  1265. The system always controls the bus. It issues commands to specific devices on the bus
  1266. and they respond by accepting data, sending data, or changing their configuration.
  1267. These commands are discussed below.
  1268.  
  1269. Note:  Devices connected to the ADB contain their own single-chip
  1270.        microprocessors, which handle both device routines and the
  1271.        ADB interface. If the system sends commands to a device with
  1272.        a duty cycle of more than 50%, the device’s microprocessor
  1273.        may become overloaded.
  1274.  
  1275. _______________________________________________________________________________
  1276.  
  1277. »Bus Commands
  1278.  
  1279. Each bus command consists of a byte that the system sends to a device connected to
  1280. the ADB. Applications may place bus commands on the network by calling the routine
  1281. ADBOp, discussed under “ADB Manager Routines” later in this chapter. There are four
  1282. bus commands; their bit layouts are shown in Figure 1.  All other bit layouts are
  1283. reserved.
  1284.  
  1285. •••Refer to Figure 1.•••
  1286.  
  1287. Figure 1–ADB Command Formats
  1288.  
  1289. The individual commands are discussed below.
  1290.  
  1291. Warning:  Values of the low bytes of the ADB command formats other than
  1292.           those shown in Figure 1 are reserved, and should not be used.
  1293.  
  1294. »SendReset
  1295.  
  1296. The SendReset command forces a hardware reset of all devices connected to the ADB.
  1297. Such a reset clears all pending device actions and places the devices in their startup
  1298. state. All devices are able to accept new ADB commands and user inputs immediately
  1299. thereafter. All devices ignore the high-order four bits of the SendReset command.
  1300.  
  1301. »Flush
  1302.  
  1303. The Flush command flushes data from the single device specified by the network address
  1304. in its high-order four bits. Network  addresses are discussed below, under “Device
  1305. Addressing”. It purges any pending user inputs and make the device ready to accept
  1306. new commands and input data.
  1307.  
  1308. »Listen
  1309.  
  1310. The Listen command is used to send instructions to devices connected to the ADB. It
  1311. transfers data from a buffer in system RAM to a register in the device specified by
  1312. the network address in its high-order four bits. The device register is specified by
  1313. the low-order two bits of the Listen command.
  1314.  
  1315. »Talk
  1316.  
  1317. The Talk command is used to fetch user inputs from devices connected to the ADB. It
  1318. is the complement of the Listen command. It transfers data from a register in the
  1319. device specified by the network address in its high-order four bits to a buffer in
  1320. system RAM. The device register is specified by the low-order two bits of the Talk
  1321. command.
  1322.  
  1323. _______________________________________________________________________________
  1324.  
  1325. »Device Registers
  1326.  
  1327. Each device connected to the ADB contains four registers, each of which may store
  1328. from two to eight bytes of data. Each register is identified by the value of the
  1329. low-order two bits in a Listen or Talk command. Registers 0 and 3 have dedicated
  1330. functions; registers 1 and 2 are used for purposes specific to each device, and need
  1331. not be present in a device.
  1332.  
  1333. Note:  ADB device registers are virtual registers; they need not be
  1334.        implemented physically.  The device firmware must only respond
  1335.        to register commands as if a register were present.
  1336.  
  1337. »Register 0
  1338.  
  1339. Device register 0 is reserved for input data. If the device has user-input data to be
  1340. fetched, it places the data in register 0 and requests service. It continues to
  1341. request service until the system retrieves its data.  The system responds to data-input
  1342. requests with the following polling sequence:
  1343.  
  1344.   •  It generates a Talk command for register 0 in each device connected
  1345.      to the ADB.
  1346.   •  If the device has data to send, it responds.  The system does not
  1347.      poll the next device until the data is exhausted.
  1348.   •  If the device has no data to send, or if its data is exhausted, the
  1349.      VIA generates an interrupt.  The system then polls the next device.
  1350.   •  This process continues until no devices request service.
  1351.  
  1352. »Register 3
  1353.  
  1354. Device register 3 is reserved for device identification data and operating flags.
  1355. Application programs may set this data with Listen commands and read it with Talk
  1356. commands. Register 3 stores 16 bits, divided into the fields shown in Figure 2.
  1357.  
  1358. •••Refer to Figure 2.•••
  1359.  
  1360. Figure 2–Format of Device Register 3
  1361.  
  1362. Except for commands that contain certain reserved device handler ID values
  1363. (listed below), every command to register 3 changes the entire register contents.
  1364. Hence to change part of the register, you should first fetch its current contents
  1365. with a Talk command and then send it an updated value with Listen. You can change
  1366. part of the contents of register 3 by using special device handler ID values, as
  1367. described below.
  1368.  
  1369. The device handler ID field indicates the device’s type. With certain devices, an
  1370. application can change the device’s mode of operation by sending it a new ID value.
  1371. If the device supports the new mode, it stores the new value in this field.
  1372.  
  1373. Warning:  You are assigned handler IDs by Apple Software Licensing, so
  1374.           they do not conflict with the values of other devices that may
  1375.           be connected to the ADB at the same time.
  1376.  
  1377. When certain reserved values are sent to the device handler ID field by a Listen
  1378. command, they are not stored in the field; instead, they cause specific device actions.
  1379. Hence these values cannot be used as device ID values. They are the following:
  1380.  
  1381.   Value  Action
  1382.  
  1383.   $00    Change bits 8–13 of register 3 to match the rest of the command;
  1384.          leave Device Handler ID value unchanged.
  1385.   $FD    Change Device Address to match bits 8–11 if the device activator
  1386.          has been depressed; leave Device Handler ID value and flags unchanged.
  1387.   $FE    Change Device Address to match bits 8–11 if the result produces no
  1388.          address duplication on the bus; leave Device Handler ID value and
  1389.          flags unchanged.
  1390.   $FF    Initiate device self-test. If self-test succeeds, leave register 3
  1391.          unchanged; if self-test fails, clear Device Handler ID field to $00.
  1392.  
  1393. Other Device Handler ID values may be stored in the field.
  1394.  
  1395. Note:  Device Handler ID values below $20 are reserved by Apple.
  1396.  
  1397. The Device Address field indicates the device’s location within the 16 possible
  1398. device locations of the ADB. An application may change its value with a Listen command.
  1399. When this field is interrogated with a Talk command, it returns a random value. This
  1400. helps you separate multiple devices that have the same ADB address; for further
  1401. information, see “Device Addressing”, below.
  1402.  
  1403. The Service Request Enable bit is set by the device to request an interrupt poll.
  1404.  
  1405. _______________________________________________________________________________
  1406.  
  1407. »Device Addressing
  1408.  
  1409. There are 16 possible direct addresses, $00–$0F, for devices connected to the ADB.
  1410. However, it is possible to connect more than one device to an address; this might
  1411. happen, for example, in a system with two alternate keyboards.
  1412.  
  1413. When several devices share a single ADB address, but there are free addresses available
  1414. in the net, the system will automatically reassign addresses until they are all
  1415. different. It will do this every time the ADB Manager is initialized or reinitialized.
  1416. To find out a device’s new address, use the calls GetIndADB or GetADBInfo, described
  1417. later in this chapter.
  1418.  
  1419. _______________________________________________________________________________
  1420.  
  1421. »Standard ADB Device Drivers
  1422.  
  1423. The Macintosh II and Macintosh SE systems contain two standard ADB drivers:
  1424.  
  1425.   •  the mouse driver, which supports the ADB mouse. The Apple mouse
  1426.      has an original ADB address of 3.
  1427.   •  the universal keyboard driver, which supports all Apple ADB keyboards.
  1428.      The Apple keyboard has an original ADB address of 2, with a Device
  1429.      Handler ID of 1 for the Macintosh II keyboard and 2 for the Apple
  1430.      Extended Keyboard.  These keyboards are described in the Toolbox
  1431.      Event Manager chapter. 
  1432.  
  1433. These drivers reside in the system ROM. In addition, ADB address 0 is reserved for
  1434. the ADB chip itself.  You can change the ADB addresses of the mouse or keyboard, as
  1435. described above under “Device Registers,” but Apple does not recommend doing so.
  1436.  
  1437. Assembly-language note:  The ADB address of the keyboard on which the
  1438.                          last-typed character was entered is now stored
  1439.                          in the global variable KbdLast. The type of the
  1440.                          keyboard on which the last-typed character was
  1441.                          entered is stored in the global variable KbdType.
  1442.                          The value of KbdType is the Device Handler ID
  1443.                          value in Register 3 of the device; values below
  1444.                          $20 are reserved by Apple.
  1445.  
  1446. The requirements for writing new ADB device drivers are discussed later in this
  1447. chapter.
  1448.  
  1449. _______________________________________________________________________________
  1450.  
  1451.  
  1452. æKY ADB…Manager…Routines
  1453. æC »ADB MANAGER ROUTINES                                      AppleDesktopBus
  1454. _______________________________________________________________________________
  1455.  
  1456. The ADB Manager consists of six routines located in the 256K ROM. You would use them
  1457. only if you needed to access bus devices directly or communicate with a special
  1458. device.
  1459.  
  1460. Some of these routines access and update information in the ADB device table, a
  1461. structure placed in the system heap by ROM code during system  startup. It lists for
  1462. each device the device’s type, its original ADB address, its current ADB address, the
  1463. address of the routine that services the device, and the address of the area in RAM
  1464. used for temporary data storage by its driver. The ADB device table is accessible
  1465. only through ADB Manager routines.
  1466.  
  1467. PROCEDURE ADBReInit;
  1468.  
  1469. Trap macro    _ADBReInit
  1470.  
  1471. ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table
  1472. to zeros and places a SendReset command on the bus to reset all devices to their
  1473. original addresses. ADBReInit has no parameters.
  1474.  
  1475. Because it does not deallocate ADB resources on the system heap, ADBReInit should not
  1476. be used for routine bus initialization. Apple strongly recommends against adding
  1477. devices while the system is running; therefore, you should never call ADBReInit.
  1478.  
  1479. ADBReInit also calls a routine pointed to by the low memory global JADBProc
  1480. at the beginning and end of its execution.  You can insert your own
  1481. preprocessing/postprocessing routine by changing the value of JADBProc; ADBReInit
  1482. conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing.  Your
  1483. procedure must restore the value of D0 and branch to the original value of JADBProc
  1484. on exit.  JADBProc should be used to de-allocate memory used by the driver (see
  1485. MacDTS Sample Code “TbltDrvr” for an example), and then it should chain to the procedure
  1486. originally found in JADBProc.
  1487.  
  1488. The complete ADBReInit sequence is therefore the following:
  1489.  
  1490.   •  JSR to JADBProc with D0 set to 0
  1491.   •  reinitialize the Apple Desktop Bus
  1492.   •  clear the ADB device table
  1493.   •  JSR to JADBProc with D0 set to 1
  1494.  
  1495. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1496.                 commandNum: INTEGER) : OSErr;
  1497.  
  1498. Trap macro    _ADBOp
  1499.  
  1500. On entry:    A0:  pointer to parameter block
  1501.              D0:  commandNum (byte)
  1502.  
  1503. Parameter block
  1504.     -->    0    buffer      pointer
  1505.     -->    4    compRout    pointer
  1506.     -->    8    data        pointer
  1507.  
  1508. On exit:     D0:  result code (byte)
  1509.  
  1510. The completion routine pointed to by compRout will be passed the following parameters
  1511. on entry:
  1512.  
  1513.              D0:  commandNum (byte)
  1514.              A0:  pointer to buffer, data stored as a Pascal string (maximum
  1515.                   8 bytes data preceded by one length byte)
  1516.              A1:  pointer to completion routine (compRout)
  1517.              A2:  pointer to optional data area (data)
  1518.  
  1519. ADBOp transmits over the bus the command byte whose value is given by commandNum. The
  1520. structure of the command byte is given earlier in Figure 1. ADBOp executes only when
  1521. the ADB is otherwise idle; otherwise it is held in a command queue. It returns an
  1522. error if the command queue is full. The length of the data buffer pointed to by
  1523. buffer is contained in its first byte, like a Pascal string. The optional data area
  1524. pointed to by data is for local storage by the completion routine pointed to by
  1525. compRout. ADBop should be used sparingly; it is not intended for polling a device. 
  1526. The host automatically polls devices with data to deliver.
  1527.  
  1528. Result codes    noErr    No error
  1529.                 –1       Unsuccessful completion
  1530.  
  1531. FUNCTION CountADBs: INTEGER;
  1532.  
  1533. Trap macro    _CountADBs
  1534.  
  1535. On exit:    D0:  number of devices (byte)
  1536.  
  1537. CountADBs returns a value representing the number of devices connected to the ADB by
  1538. counting the number of entries in the device table. It has no arguments and returns
  1539. no error codes.
  1540.  
  1541. FUNCTION GetIndADB (VAR info: ADBDataBlock;
  1542.                     devTableIndex: INTEGER) : ADBAddress;
  1543.  
  1544. Trap macro    _GetIndADB
  1545.  
  1546. On entry:    A0:  pointer to parameter block
  1547.              D0:  entry index number; range = 1..CountADBs (byte)
  1548.  
  1549. Parameter block
  1550.     <--    0    device type                byte    (handler ID)
  1551.     <--    1    original ADB address       byte
  1552.     <--    2    service routine address    pointer (compRout)
  1553.     <--    6    data area address          pointer (data)
  1554.  
  1555. On exit:     D0:  positive value:  current ADB address (byte)
  1556.                   negative value:  error code (byte)
  1557.  
  1558. GetIndADB returns information from the ADB device table entry whose index number is
  1559. given by devTableIndex. ADBDataBlock has this form:
  1560.  
  1561. TYPE  ADBDataBlock =
  1562.              PACKED RECORD
  1563.                devType:         SignedByte; {device type (handler ID)}
  1564.                origADBAddr:     SignedByte; {original ADB address}
  1565.                dbServiceRtPtr:  Ptr;        {service routine address (compRout)}
  1566.                dbDataAreaAddr:  Ptr         {data area address (data)}
  1567.              END;
  1568.  
  1569. GetIndADB returns the current ADB address of the device. If it is unable to complete
  1570. execution successfully, GetIndADB returns a negative value.
  1571.  
  1572. FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1573.  
  1574. Trap macro    _GetADBInfo
  1575.  
  1576. On entry:    A0:  pointer to parameter block
  1577.              D0:  ADB address of the device (byte)
  1578.  
  1579. Parameter block
  1580.     <--    0    device handler ID          byte
  1581.     <--    1    original ADB address       byte
  1582.     <--    2    service routine address    pointer (compRout)
  1583.     <--    6    data area address          pointer (data)
  1584.  
  1585. On exit:     D0:  result code (byte)
  1586.  
  1587. GetADBInfo returns information from the ADB device table entry of the device whose
  1588. ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under
  1589. “GetIndADB”.
  1590.  
  1591. Result codes    noErr    No error
  1592.  
  1593. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1594.  
  1595. Trap macro    _SetADBInfo
  1596.  
  1597. On entry:    A0:  pointer to parameter block
  1598.              D0:  ADB address of the device (byte)
  1599.  
  1600. Parameter block
  1601.     -->    0    service routine address    pointer (compRout)
  1602.     -->    4    data area address          pointer (data)
  1603.  
  1604. On exit:     D0:  result code (byte)
  1605.  
  1606. SetADBInfo sets the service routine address and the data area address in the ADB
  1607. device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock
  1608. has this form:
  1609.  
  1610. TYPE  ADBSetInfoBlock =
  1611.                RECORD
  1612.                  siServiceRtPtr:  Ptr;  {service routine address (compRout)}
  1613.                  siDataAreaAddr:  Ptr   {data area address (data)}
  1614.                END;
  1615.  
  1616. Result codes    noErr    No error
  1617.  
  1618. Warning:  You should send a Flush command to the device after calling it
  1619.           with SetADBInfo, to prevent it sending old data to the new data
  1620.           area address.
  1621.  
  1622. _______________________________________________________________________________
  1623.  
  1624.  
  1625. æKY Writing…ADB…Device…Drivers
  1626. æC »WRITING ADB DEVICE DRIVERS                                AppleDesktopBus
  1627. _______________________________________________________________________________
  1628.  
  1629. Drivers for devices connected to the ADB have the following special requirements:
  1630.  
  1631.   •  Each ADB device driver must reside in a resource of type 'ADBS'.
  1632.      (An example 'ADBS' resource is available in MacDTS Sample Code
  1633.      “TbltDrvr.”) This type has two sections: initialization and driver code.
  1634.   •  The initialization section of each ADB device driver must support the
  1635.      installation procedure described below.
  1636.  
  1637. When the system calls an ADB device driver, it passes it the following values:
  1638.  
  1639.   •  Register A0 points to the data buffer, which is formatted as a
  1640.      Pascal string (buffer).
  1641.   •  Register A1 points to the driver’s completion routine (compRout).
  1642.   •  Register A2 points to the optional data area (data).
  1643.   •  Register D0 contains the ADB command that resulted in the driver
  1644.      being called (commandNum).
  1645.  
  1646. The ADB driver should handle the ADB command passed to it and store any resulting
  1647. input data by an appropriate action, such as by posting an event or moving the cursor.
  1648.  
  1649. Note:  Events posted from keyboards connected to the ADB now have an
  1650.        expanded structure. For more information, see the Toolbox Event
  1651.        Manager chapter.
  1652.  
  1653. _______________________________________________________________________________
  1654.  
  1655. »Installing an ADB Driver
  1656.  
  1657. The Start Manager (described in this volume) finds all the ADB devices connected to
  1658. the system and places their device types and ADB addresses in the ADB device table.
  1659. It then calls the initialization section of each ADB device driver by executing the
  1660. initialization code in its 'ADBS' resource.
  1661.  
  1662. As a minimum, the initialization section of each ADB device driver must do the following:
  1663.  
  1664.   •  The driver must allocate all the memory required by the driver code
  1665.      in one or more nonrelocatable blocks in the system heap area.
  1666.   •  The driver must install its own preprocessing/postprocessing routine
  1667.      (if any) as described above under “ADBReInit”.
  1668.   •  Finally, the driver must initialize the service routine address and
  1669.      data area address of its entry in the ADB device table, using SetADBInfo.
  1670.  
  1671. _______________________________________________________________________________
  1672.  
  1673.  
  1674. æKY Summary…of…the…ADB
  1675. æC »SUMMARY OF THE ADB MANAGER                                AppleDesktopBus
  1676. _______________________________________________________________________________
  1677.  
  1678. Data Types
  1679.  
  1680. TYPE
  1681.   ADBDataBlock =
  1682.          PACKED RECORD
  1683.            devType:         SignedByte;  {Handler ID}
  1684.            origADBAddr:     SignedByte;  {original ADB address}
  1685.            dbServiceRtPtr:  Ptr;         {service routine address (compRout)}
  1686.            dbDataAreaAddr:  Ptr          {data area address (area)}
  1687.          END;
  1688.  
  1689.   ADBSetInfoBlock =
  1690.            RECORD
  1691.              siServiceRtPtr:  Ptr;  {service routine address}
  1692.              siDataAreaAddr:  Ptr   {data area address}
  1693.            END;
  1694.  
  1695. _______________________________________________________________________________
  1696.  
  1697. Routines
  1698.  
  1699. Initializing the ADB Manager
  1700.  
  1701. PROCEDURE ADBReInit;
  1702.  
  1703. Communicating Through the ADB
  1704.  
  1705. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1706.                 commandNum: INTEGER) : OSErr;
  1707.  
  1708. Getting ADB Device Information
  1709.  
  1710. FUNCTION CountADBs:  INTEGER;
  1711. FUNCTION GetIndADB   (VAR info: ADBDataBlock;
  1712.                       devTableIndex: INTEGER) : ADBAddress;
  1713. FUNCTION GetADBInfo  (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1714.  
  1715. Setting ADB Device Information
  1716.  
  1717. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1718.  
  1719. _______________________________________________________________________________
  1720.  
  1721. Assembly-Language Information
  1722.  
  1723. Variables
  1724.  
  1725. JADBProc    Pointer to ADBReInit preprocessing/postprocessing routine
  1726. KbdLast     ADB address of the keyboard last used (byte)
  1727. KbdType     Keyboard type of the keyboard last used (byte)
  1728.  
  1729. Routines
  1730.  
  1731. Trap macro     On entry                               On Exit
  1732.  
  1733. _ADBReInit
  1734.  
  1735. _ADBOp         A0:  pointer to parameter block        D0:  result code (byte)
  1736.                     buffer (pointer)
  1737.                     compRout (pointer)
  1738.                     data (pointer)
  1739.                D0:  commandNum (byte)
  1740.  
  1741. _CountADBs                                            D0:  result code (byte)
  1742.  
  1743. _GetIndADB     A0:  pointer to parameter block        D0:  positive value:
  1744.                     device type (byte)                       current ADB
  1745.                     original ADB address (byte)              address (byte)
  1746.                     service routine address (pointer)        negative value:
  1747.                     data area address (pointer)              error code (byte)
  1748.                D0:  entry index number;
  1749.                     range = 1..CountADBs (byte)
  1750.  
  1751. _GetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1752.                     device handler ID (byte)           
  1753.                     original ADB address (byte)   
  1754.                     service routine address (pointer)   
  1755.                     data area address (pointer)
  1756.                D0:  current ADB address of the device (byte)
  1757.  
  1758. _SetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1759.                     service routine address (pointer)   
  1760.                     data area address (pointer)
  1761.                D0:  current ADB address of the device (byte)
  1762.  
  1763. Further Reference:
  1764. _______________________________________________________________________________
  1765. Toolbox Event Manager
  1766. Technical Note #143, Don’t Call ADBReInit on the SE with System 4.1
  1767. Technical Note #160, Key Mapping
  1768. Technical Note #206, Space Aliens Ate My Mouse
  1769. “Macintosh Family Hardware Reference”
  1770.  
  1771.  
  1772. æKY AppleTalkManager
  1773. æC 
  1774. _______________________________________________________________________________
  1775.  
  1776. APPLETALK MANAGER
  1777. _______________________________________________________________________________
  1778.  
  1779. About…the…AppleTalk…Chapter
  1780. About…the…AppleTalk…Manager
  1781.     Changes…to…the…AppleTalk…Manager
  1782.     AppleTalk…Protocols
  1783.     AppleTalk…Device…Drivers,…'adev'…Files,…and…the…LAP…Manager
  1784. Using…the…AppleTalk…Manager
  1785.     Determining…Whether…AppleTalk…Phase…2…Drivers…Are…Present
  1786.     Determining…Which…AppleTalk…Protocol…to…Use
  1787. The….MPP…Driver
  1788.     Getting…Information…About…the….MPP…Driver
  1789.     A…New…NBP…Wildcard…Character
  1790. The…LAP…Manager
  1791.     The…AppleTalk…Transition…Queue
  1792.     Adding…and…Removing…AppleTalk…Transition…Queue…Entries
  1793.     Sending…Messages…to…the…AppleTalk…Transition…Queue
  1794.     How…the…AppleTalk…Manager…Calls…Your…Transition…Queue…Routine
  1795.     The…LAP…Manager…802.2…Protocol
  1796.     Attaching…and…Detaching…802.2…Protocol…Handlers
  1797. AppleTalk…Data…Stream…Protocol…(ADSP)
  1798.     Using…ADSP
  1799.     The…ADSP…Connection…Control…Block
  1800.     The….DSP…Parameter…Block
  1801.     Opening…and…Maintaining…an…ADSP…Connection
  1802.     Creating…and…Using…a…Connection…Listener
  1803.     Writing…a…User…Routine…For…Connection…Events
  1804.     DSP…Driver…Commands
  1805.     Establishing…and…Terminating…an…ADSP…Connection
  1806.     Establishing…and…Terminating…an…ADSP…Connection…Listener
  1807.     Maintaining…an…ADSP…Connection
  1808. The….ATP…Driver
  1809.     Canceling…All…Calls…to…the…ATPGetRequest…Function
  1810.     Setting…the…Timeout…Value…For…the…ATP…Release…Timer
  1811. The….XPP…Driver
  1812.     Using…the….XPP…Driver…to…Obtain…Zone…Information
  1813.     XPP…Driver…Routines
  1814. The….ENET…Driver
  1815.     Changing…the…Ethernet…Hardware…Address
  1816.     Opening…the….ENET…Driver
  1817.     Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  1818.     Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  1819.     Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  1820.     How…the….ENET…Driver…Calls…Your…Protocol…Handler
  1821.     How…Your…Protocol…Handler…Calls…the….ENET…Driver
  1822.     ENET…Driver…Routines
  1823.     Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  1824.     Writing…and…Reading…Packets…Using…the…Default…Protocol…Handler
  1825.     Adding…and…Removing…Ethernet…Multicast…Addresses
  1826. Summary…of…the…AppleTalk…Manager
  1827.     AppleTalk…Constants
  1828.     AppleTalk…Data…Types
  1829.     AppleTalk…Routines
  1830.     AppleTalk…Result…codes
  1831.     Assembly-language…Information…for…AppleTalk
  1832.     _______________________________________________________________________________
  1833.  
  1834.  
  1835.  
  1836. æKY About…the…AppleTalk…Chapter
  1837. æC »ABOUT THIS CHAPTER                                                   AppleTalk Manager
  1838. _______________________________________________________________________________
  1839.  
  1840. AppleTalk is a communication network system including personal computer
  1841. workstations, computers acting as file servers and print servers, printers, and
  1842. a variety of types of communication hardware and software. The AppleTalk Manager
  1843. provides an interface to this communication network system for applications
  1844. running on Macintosh computers. This chapter describes the changes to the
  1845. AppleTalk Manager introduced as AppleTalk Phase 2 and included with system
  1846. software version 7.0. This chapter supplements the information in the AppleTalk
  1847. Manager chapters of Inside Macintosh, Volumes II and V.
  1848.  
  1849. This chapter describes 
  1850.   •   new routines for the .MPP, .ATP, and .XPP device drivers
  1851.  
  1852.   •   a new wildcard character for use with the Name-Binding Protocol
  1853.  
  1854.   •   a new system queue, called the AppleTalk Transition Queue
  1855.  
  1856.   •   a new set of operating system utilities, collectively called the LAP
  1857.       Manager.
  1858.  
  1859.   •   the .ENET driver and the routines your application can use to control
  1860.       this driver
  1861.  
  1862.   •   the application interface routines provided by a new AppleTalk protocol,
  1863.       the AppleTalk Data Stream Protocol
  1864.  
  1865. Together with the AppleTalk Manager chapters of Volumes II and V, this chapter
  1866. describes the routines that your application can use to send and receive
  1867. information within an AppleTalk network system . Because the AppleTalk network
  1868. system includes both hardware and software, and because the software includes
  1869. not only the AppleTalk Manager but file servers, print servers, internet
  1870. routers, drivers for circuit cards, and so forth, the information in Inside
  1871. Macintosh constitutes only a small part of the body of literature documenting
  1872. AppleTalk.
  1873.  
  1874. For a detailed description of AppleTalk protocols, see Inside AppleTalk. For a
  1875. complete description of the LAP Manager, EtherTalk, and alternate AppleTalk
  1876. connections, see the AppleTalk Connections Programmer’s Guide. To learn how to
  1877. install and operate an AppleTalk internet, see the AppleTalk Internet Router
  1878. Administrator’s Guide and the AppleTalk Phase 2 Introduction and Upgrade Guide.
  1879. For an introduction to the hardware and software of an entire AppleTalk network,
  1880. see Understanding Computer Networks and the AppleTalk Network System Overview.
  1881. For information on designing circuit cards and device drivers for Macintosh
  1882. computers, see Designing Cards and Drivers for the Macintosh Family.
  1883.  
  1884. You can install the Phase 2 versions of the AppleTalk drivers on any Macintosh
  1885. computer other than the Macintosh XL, Macintosh 128K, Macintosh 512K, and
  1886. Macintosh 512K enhanced computers. If you want to provide AppleTalk Phase 2
  1887. device drivers with your product, you must obtain a license from Apple Software
  1888. Licensing.
  1889.  
  1890. _______________________________________________________________________________
  1891.  
  1892. æKY About…the…AppleTalk…Manager
  1893. æC »ABOUT THE APPLETALK MANAGER                                          AppleTalk Manager
  1894. _______________________________________________________________________________
  1895.  
  1896. The AppleTalk Manager includes a number of protocols that are implemented in
  1897. various device drivers. The AppleTalk Manager also includes the LAP Manager,
  1898. which interfaces the AppleTalk data links to the AppleTalk protocols; and
  1899. hardware device drivers for specific networks. The AppleTalk data links are
  1900. contained in files of type 'adev', sometimes referred to as 'adev' files. This
  1901. section lists the new features that have been introduced as AppleTalk Phase 2,
  1902. describes the organization of the AppleTalk Manager, and briefly discusses what
  1903. each component of the AppleTalk Manager does.
  1904.  
  1905.  
  1906. _______________________________________________________________________________
  1907.  
  1908. æKY Changes…to…the…AppleTalk…Manager
  1909. æC »Changes to the AppleTalk Manager                                     AppleTalk Manager
  1910. _______________________________________________________________________________
  1911.  
  1912. The features that have been introduced as AppleTalk Phase 2 include
  1913.  
  1914.   •   a new .MPP driver function that returns information about the .MPP driver
  1915.  
  1916.   •   a new protocol, the AppleTalk Data Stream Protocol (ADSP), which provides
  1917.       full-duplex data stream communications for use by applications; see
  1918.       “AppleTalk Data Stream Protocol”
  1919.  
  1920.   •   improvements to the Zone Information Protocol (ZIP) that allow a single
  1921.       network (other than LocalTalk) to contain more than one zone; see
  1922.       “Obtaining Zone Information.”
  1923.  
  1924.   •   new functions for the .XPP device driver that provide information from
  1925.       ZIP about zones; see “The .XPP Driver”
  1926.  
  1927.   •   a new Name Binding Protocol (NBP) wildcard character that can substitute
  1928.       for one or more characters in AppleTalk names; see “A New NBP Wildcard
  1929.       Character”
  1930.  
  1931.   •   the AppleTalk Transition Queue, an operating system queue that can notify
  1932.       your application each time an AppleTalk driver is opened or closed, or
  1933.       certain other transitions occur; see “The AppleTalk Transition Queue”
  1934.  
  1935.   •   the LAP Manager, a new set of operating system utilities that provide a
  1936.       standard interface between the AppleTalk protocols and the data links
  1937.       used by Appletalk, such as EtherTalk, LocalTalk, and TokenTalk; see “The
  1938.       LAP Manager”
  1939.  
  1940.   •   the .ENET driver, an Ethernet driver for the EtherTalk NuBus card that is
  1941.       manufactured by Apple Computer, Inc.; see “The .ENET Driver”
  1942.  
  1943.   •   an implementation of the IEEE 802.2 protocol, which allows you to attach
  1944.       and detach your own protocol handlers for EtherTalk and TokenTalk data
  1945.       packets; see “The LAP Manager 802.2 Protocol”
  1946.  
  1947.   •   new .ATP driver functions that allow you to set a value for the .ATP
  1948.       release timer and to cancel all pending asynchronous calls to the
  1949.       ATPGetRequest function for a specific socket; see “The .ATP Driver”
  1950. _______________________________________________________________________________
  1951.  
  1952. æKY AppleTalk…Protocols
  1953. æC »AppleTalk Protocols                                                  AppleTalk Manager
  1954. _______________________________________________________________________________
  1955.  
  1956. The AppleTalk Manager comprises the following protocols:
  1957.  
  1958.   •   LocalTalk Link Access Protocol (LLAP)
  1959.   •   Datagram Delivery Protocol (DDP)
  1960.   •   Routing Table Maintenance Protocol (RTMP)
  1961.   •   AppleTalk Transaction Protocol (ATP)
  1962.   •   Name-Binding Protocol (NBP)
  1963.   •   AppleTalk Echo Protocol (AEP)
  1964.   •   Zone Information Protocol (ZIP)
  1965.   •   AppleTalk Session Protocol (ASP)
  1966.   •   AppleTalk Data Stream Protocol (ADSP)
  1967.   •   AppleTalk Filing Protocol (AFP)
  1968.  
  1969. The EtherTalk Link Access Protocol, TokenTalk Link Access Protocol, and other
  1970. Link Access Protocols provide interfaces between the AppleTalk Manager and the
  1971. different types of data link hardware used by AppleTalk.
  1972.  
  1973. Note:  The LocalTalk Link Access Protocol (LLAP) was originally called the
  1974. AppleTalk Link Access Protocol (ALAP). It has been renamed to avoid confusion
  1975. with the EtherTalk Link Access Protocol and other link access protocols.
  1976.  
  1977. Figure 29-1 shows the relationships among the various AppleTalk protocols. A
  1978. line going from a protocol to another protocol above or below it in the figure
  1979. indicates that the upper protocol is a client of the lower protocol; that is,
  1980. the upper protocol uses services provided by the lower protocol in order to
  1981. carry out some functions.
  1982.  
  1983. Note:  The various AppleTalk protocols are sets of rules, not computer programs,
  1984. and so can be implemented in many different ways on many different systems. All
  1985. of the AppleTalk protocol functions that you can address or control from a
  1986. Macintosh application are implemented as Macintosh device drivers or managers.
  1987. Many other features of these protocols are implemented in software located only
  1988. on internet routers that are not used to run general applications. Some parts of
  1989. protocols are implemented by server software such as file servers and print
  1990. servers. Therefore, when this chapter refers to a protocol as “doing” or 
  1991. “controlling” something, you should understand the statement to mean that some
  1992. program that implements the protocol actually carries out the operation.
  1993.  
  1994. ø 29.1  AppleTalk Protocols
  1995.  
  1996. A link access protocol controls the access of the node to the network hardware,
  1997. making it possible for many nodes to share the same communication hardware. Each
  1998. link access protocol assigns a node ID to the node and decodes the node
  1999. addresses of messages it receives. A link access protocol provides node-to-node
  2000. delivery of data packets. Examples of link access protocols include the
  2001. LocalTalk Link Access Protocol, the EtherTalk Link Access Protocol, and the
  2002. TokenTalk Link Access Protocol.
  2003.  
  2004. Whereas earlier implementations of AppleTalk were restricted to one 16-bit
  2005. network number per cable (that is, one network number for all nodes connected
  2006. with no intervening routers) and 254 nodes per network number, AppleTalk Phase 2
  2007. allows more than one network number for each cable (other than LocalTalk, which
  2008. is still limited to one network number on a cable). Each node in a network other
  2009. than LocalTalk must be specified by both its 16-bit network number and its 8-bit
  2010. node ID. In principle, each cable (other than LocalTalk) can now have over 16
  2011. million (224) nodes. In any specific implementation, the hardware or software
  2012. might limit the network to fewer nodes.
  2013.  
  2014. Note:  Before the introduction of AppleTalk Phase 2, AppleTalk allowed only one
  2015. network number per cable (that is, one network number for all nodes connected
  2016. with no intervening routers), and the term network was used to include all of
  2017. the nodes connected by a single cable. Under AppleTalk Phase 2, however, more
  2018. than one network number can be assigned to a single cable. The term network is
  2019. now sometimes used to refer to the collection of all the nodes that share a
  2020. single network number, and is sometimes used in the older sense to refer to all
  2021. nodes connected with no intervening routers. In the latter case, you could say
  2022. that a single network can have a range of network numbers. Because of this
  2023. ambiguity, it is best to avoid using the term network without modifiers. 
  2024.  
  2025. The Datagram Delivery Protocol provides socket-to-socket delivery of data
  2026. packets within an AppleTalk internet. A DDP packet’s address includes the socket
  2027. number, node ID, and network number. Application-interface routines for DDP are
  2028. described in “Datagram Delivery Protocol” in the AppleTalk Manager chapter of
  2029. Volume II.
  2030.  
  2031. The Routing Table Maintenance Protocol is used by routers on an AppleTalk
  2032. internet to determine how to forward a data packet to the network number to
  2033. which it is addressed. The RTMP implementation on a router maintains a table,
  2034. called a routing table, that specifies the shortest path to each possible
  2035. destination network number. The AppleTalk protocol software in a workstation
  2036. contains only a small part of RTMP, called the RTMP stub, that DDP uses to
  2037. determine the network number (or range of network numbers) of the network cable
  2038. to which the node is connected and the network number and node ID of one router
  2039. on that network cable. There is no application interface to the RTMP stub.
  2040.  
  2041. The AppleTalk Transaction Protocol provides loss-free communications by
  2042. retransmitting any data packets that are lost. Although—as you can see from
  2043. Figure 29-1—the AppleTalk Manager provides high-level protocols that are clients
  2044. of ATP, many applications use ATP directly to transmit data over an AppleTalk
  2045. internet. The application interface to ATP is described in the AppleTalk Manager
  2046. chapter of Volume II. There are some enhancements to ATP in AppleTalk Phase 2,
  2047. described in “Changes to the .ATP Driver” later in this chapter.
  2048.  
  2049. The Name-Binding Protocol maintains a table that contains the internet address
  2050. and name of each entity in the node that is visible to other entities on the
  2051. internet. The internet address includes the socket number, node ID, and network
  2052. number. The name consists of three fields: the object, type, and zone. The
  2053. object and type are assigned by the entity itself and can be anything the user
  2054. or application assigns. A zone is a logical grouping of a subset of the nodes on
  2055. the internet. The zone field of the name is the zone in which the node resides.
  2056.  
  2057. NBP also allows its clients to obtain the internet address of any
  2058. network-visible entity in the internet by providing its name. NBP maps this name
  2059. to an internet address, thus providing the link between the user-supplied name
  2060. for an entity and the internet address that is used by DDP to send and receive
  2061. data packets. The application interface to NBP is described in the AppleTalk
  2062. Manager chapter of Volume II. There is one enhancement to NBP in AppleTalk Phase
  2063. 2, described in “A New NBP Wildcard Character” later in this chapter.
  2064.  
  2065. The AppleTalk Echo Protocol listens for special packets sent by other nodes and,
  2066. when it receives such a packet, echoes it back to the sender. The AEP is used by
  2067. some clients of DDP to determine whether another node (known to have AEP) can be
  2068. accessed over the internet, and to determine how long it takes a packet to reach
  2069. another node. There is no application interface to AEP.
  2070.  
  2071. The Zone Information Protocol maintains a table in each router, called the zone
  2072. information table, that lists the relationships between zone names and networks.
  2073. In AppleTalk Phase 2, a network (other than LocalTalk) can contain more than one
  2074. zone or a zone can contain more than one network. You can use .XPP driver
  2075. routines to obtain information from ZIP; these routines are discussed in 
  2076. “Obtaining Zone Information” later in this chapter.
  2077.  
  2078. The AppleTalk Session Protocol sets up and maintains sessions between a
  2079. workstation and a server. A session consists of a logical (as opposed to
  2080. physical) connection between two entities on the internet. ASP is a
  2081. nonsymmetrical protocol; that is, only one of the two entities involved in the
  2082. session (the workstation) can send commands; the other entity (the server) is
  2083. restricted to responding to the commands. ASP is used by the AppleTalk Filing
  2084. Protocol, for example, to allow a user to manipulate files on a file server. As
  2085. long as the session is open, the workstation can request directory information,
  2086. change file names, and so forth. The file server must respond to the
  2087. workstation’s commands and cannot initiate any actions on its own. ASP is
  2088. discussed in the AppleTalk Manager chapter of Volume V.
  2089.  
  2090. The AppleTalk Data Stream Protocol appears to its clients to maintain an open
  2091. pipeline between two entities on the internet. Either entity can write a stream
  2092. of bytes to the pipeline, or read data bytes from the pipeline. ADSP is a
  2093. symmetrical protocol; that is, the two clients at either end of the connection
  2094. are equal and can perform exactly the same operations. ADSP is especially useful
  2095. for exchanging information between two equal entities, as in a telephone
  2096. communication network, or for sending or receiving a continuous stream of data,
  2097. as required by a terminal emulation program, for example. Because ADSP is a
  2098. client of DDP, the data is actually sent as data packets, allowing ADSP to
  2099. correct errors in transmission in a way that would not be possible for a true
  2100. data stream connection. Thus, ADSP retains many of the advantages of a
  2101. transaction-based protocol while providing to its clients a full-duplex data
  2102. stream. ADSP is discussed in the sections “Using ADSP” and “.DSP Driver
  2103. Functions” later in this chapter.
  2104.  
  2105. The AppleTalk Filing Protocol provides an interface between an application and a
  2106. file server. AFP is a client of ASP, and is used to access AppleShare file
  2107. servers on Macintosh computer workstations. When the user opens a session with
  2108. an AppleShare file server over an internet, it appears to any application
  2109. running on the workstation that uses File Manager routines as if the files on
  2110. the file server were located on a disk drive connected to the workstation. The
  2111. application interface to AFP is described in the AppleTalk Manager chapter of
  2112. Volume V. 
  2113. _______________________________________________________________________________
  2114.  
  2115. æKY AppleTalk…Device…Drivers,…'adev'…Files,…and…the…LAP…Manager
  2116. æC »AppleTalk Device Drivers, 'adev' Files, and the LAP Manager          AppleTalk Manager
  2117. _______________________________________________________________________________
  2118.  
  2119. A protocol is only a set of rules, not a computer program. The various AppleTalk
  2120. protocols are implemented as Macintosh device drivers, including
  2121.  
  2122.   •   the .MPP driver, which implements LLAP, DDP, NBP, AEP, and the RTMP stub
  2123.   •   the .ATP driver, which implements ATP
  2124.   •   the .XPP driver, which implements ASP and the workstation portions of ZIP
  2125.       and AFP
  2126.   •   the .DSP driver, which implements ADSP
  2127.   •   the .ENET driver, which implements Ethertalk
  2128.  
  2129. AppleTalk can also include one or more 'adev' files. An 'adev' file has file
  2130. type 'adev' and contains a link access protocol implementation for a network 
  2131. (ELAP for Ethernet, for example). The LAP Manager makes it possible for the user
  2132. to select among 'adev' files by using the Network control panel to control which
  2133. network is used for the node’s AppleTalk connection. The 'adev' file and LAP
  2134. Manager work together with the Network control panel (Network cdev) file. When
  2135. the user selects a connection from the Network control panel, the LAP Manager
  2136. routes AppleTalk communications through the selected link access protocol and
  2137. hence through the selected hardware.
  2138.  
  2139. The AppleTalk device drivers, LAP Manager, and 'adev' files are shown in Figure
  2140. As you can see from the figure, each device driver implements one or more
  2141. AppleTalk protocols.
  2142.  
  2143. ø 29.2  AppleTalk Device Drivers
  2144.  
  2145. Figure 29-3 shows the interfaces between a general application on a Macintosh
  2146. computer being used as an AppleTalk workstation and the AppleTalk protocols, the
  2147. LAP Manager, and the Ethernet hardware device driver. The lines connecting the
  2148. application to the various components of AppleTalk indicate which components
  2149. have application interfaces. As discussed in the preceding section, “AppleTalk
  2150. Protocols,” each application interface is described at least in part in this or
  2151. another volume of Inside Macintosh. 
  2152.  
  2153. ø 29.3  AppleTalk Application Interfaces.
  2154.  
  2155. _______________________________________________________________________________
  2156.  
  2157. æKY Using…the…AppleTalk…Manager
  2158. æC »USING THE APPLETALK MANAGER                                          AppleTalk Manager
  2159. _______________________________________________________________________________
  2160.  
  2161. This section describes how to determine whether AppleTalk Phase 2 drivers are
  2162. present and gives some advice on how to select the AppleTalk protocol that best
  2163. servers your purposes. This section also describes how to use the features added
  2164. to AppleTalk with Phase 2 and provides programming examples of the use of the 
  2165. .DSP driver and several other new AppleTalk features.
  2166.  
  2167. _______________________________________________________________________________
  2168.  
  2169. æKY Determining…Whether…AppleTalk…Phase…2…Drivers…Are…Present
  2170. æC »Determining Whether AppleTalk Phase 2 Drivers Are Present            AppleTalk Manager
  2171. _______________________________________________________________________________
  2172.  
  2173. Once the .MPP driver has been loaded into memory, you can use the Gestalt
  2174. function to check the version of AppleTalk. The Gestalt function returns the
  2175. version of the .MPP driver; if the version is greater than or equal to 53, then
  2176. the .MPP driver supports AppleTalk Phase 2, and you can assume the other Phase 2
  2177. drivers are present as well.
  2178.  
  2179. Alternatively, you can call the SysEnvirons function as described in Chapter 1
  2180. of Volume V. If the atDrvrVersNum field of the SysEnvRec record returned by this
  2181. function is greater than or equal to 53, the .MPP driver supports AppleTalk
  2182. Phase 2.
  2183.  
  2184. _______________________________________________________________________________
  2185.  
  2186. æKY Determining…Which…AppleTalk…Protocol…to…Use
  2187. æC »Determining Which AppleTalk Protocol to Use                          AppleTalk Manager
  2188. _______________________________________________________________________________
  2189.  
  2190. AppleTalk offers a variety of communication protocols at a variety of levels.
  2191. Your choice of protocol or protocols to use depends primarily on your needs, and
  2192. can be influenced by your familiarity with network communications in general. 
  2193. You can write your own protocol handlers and call the low-level AppleTalk device
  2194. drivers directly. However, if you are not communications expert and have no
  2195. desire to design your own network protocols, you should probably use one of
  2196. three AppleTalk protocols for sending and receiving data over the AppleTalk
  2197. internet: the AppleTalk Transaction Protocol (ATP), the AppleTalk Session
  2198. Protocol (ASP), or the AppleTalk Data Stream Protocol (ADSP). 
  2199.  
  2200. ATP is a lower-level protocol than ASP or ADSP. You cannot use ATP to establish
  2201. a session and keep it open; rather, you request data from another socket or send
  2202. a response (up to eight packets of data) from your socket to another socket that
  2203. has requested data. You should use ATP if you want only to send a small amount
  2204. of data and do not need the overhead required to maintain an open connection.
  2205. ATP is described in the AppleTalk Manager chapters of Volume II and Volume V.
  2206.  
  2207. ASP is designed to support a session between a server and one or more
  2208. workstations. It is an asymmetrical protocol: all exchanges are initiated by a
  2209. workstation and responded to by a server. The server cannot initiate an exchange
  2210. of data except to send an attention message to a workstation, asking the
  2211. workstation to request data from the server. An application running on a
  2212. workstation must make calls to ASP to communicate with any server that uses ASP.
  2213. If you want to develop a new type of asymmetrical, transaction-oriented server,
  2214. you should consider using ASP to implement it. ASP is described in the AppleTalk
  2215. Manager chapter of Volume V.
  2216.  
  2217. ADSP is a symmetrical protocol that you can use to establish and maintain a
  2218. connection between two equal entities. Either end of an ADSP connection can send
  2219. data at any time. Although ADSP is a client of DDP, and therefore sends and
  2220. receives data in packets (as do ATP and ASP), to an application using ADSP the
  2221. data appears to be sent and received as a continuous stream. In addition to the
  2222. duplex data stream maintained by an ADSP session, ADSP allows either end of a
  2223. connection to send an attention message to the other end. You can use ADSP to
  2224. establish two-way communication between computers, such as an interoffice party
  2225. line or a terminal-emulation program. If you want to develop a server that
  2226. requires two-way communication, you should consider using ADSP to implement it.
  2227. ADSP is described in “Using ADSP” later in this chapter.
  2228.  
  2229. _______________________________________________________________________________
  2230.  
  2231. æKY The….MPP…Driver
  2232. æC »THE .MPP DRIVER                                                      AppleTalk Manager
  2233. _______________________________________________________________________________
  2234.  
  2235. Within the AppleTalk Manager, the .MPP driver implements the Routing Table
  2236. Maintenance Protocol (RTMP) stub, the Name Binding Protocol (NBP), the AppleTalk
  2237. Echo Protocol (AEP), the Datagram Delivery Protocol (DDP), and the LocalTalk
  2238. Link Access Protocol (LLAP). The AppleTalk Phase 2 version of the .MPP driver
  2239. includes a new function that returns information about the .MPP driver,
  2240. functions that send messages to routines in the AppleTalk Transition Queue, and
  2241. a new wildcard character for NBP.
  2242.  
  2243. _______________________________________________________________________________
  2244.  
  2245. æKY Getting…Information…About…the….MPP…Driver
  2246. æC »Getting Information About the .MPP Driver                            AppleTalk Manager
  2247. _______________________________________________________________________________
  2248.  
  2249. You can use the PGetAppleTalkInfo function to obtain information about the .MPP
  2250. driver. In addition to the node ID and other information pointed to by the
  2251. ABusVars global variable (discussed in the AppleTalk Manager chapter of Volume
  2252. II), the PGetAppleTalkInfo function returns 
  2253.  
  2254.   •   a pointer to the .MPP driver’s device control entry data structure (DCE)
  2255.  
  2256.   •   configuration flags, which indicate the status of certain conditions that
  2257.       are set at startup
  2258.  
  2259.   •   a value (the selfSend flag) that indicates whether the node can send
  2260.       packets to itself
  2261.  
  2262.   •   the network number range for the network to which the node is attached
  2263.  
  2264.   •   the 8-bit node ID and 16-bit network number of the node
  2265.  
  2266.   •   the 8-bit node ID and 16-bit network number of the last router from which
  2267.       the node has heard
  2268.  
  2269.   •   the maximum capacities of the .MPP driver—such as the maximum number of
  2270.       protocol handlers and the maximum number of static sockets allowed by
  2271.       this driver
  2272.  
  2273.   •   a pointer to the registered names queue
  2274.  
  2275.   •   the node address of the node on the underlying data link (for example,
  2276.       the Ethernet hardware address)
  2277.  
  2278.   •   the node’s zone name
  2279.  
  2280. The data link address (for example, the Ethernet hardware address) and the zone
  2281. name are returned only for extended networks; that is, network types that allow
  2282. more than one network per cable. You must allocate memory for and provide
  2283. pointers to the data buffers into which the PGetAppleTalkInfo function returns
  2284. the data link address and zone name. You use the laLength parameter to specify
  2285. the length of the data link address you want returned; the function returns the
  2286. actual length of the data in the laLength parameter and returns the data in the
  2287. buffer you provide.
  2288.  
  2289. Note:  Always use the PGetAppleTalkInfo function to obtain information about the
  2290. .MPP driver. You can no longer rely on the validity of the global variables
  2291. described in the AppleTalk chapter of Inside Macintosh, Volume II.
  2292.  
  2293. FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  2294.  
  2295. Parameter block
  2296.   ¨  16  ioResult  word  result code 
  2297.   Æ  26  csCode  word  always PGetAppleTalkInfo
  2298.   Æ  28  version  word  version of function
  2299.   ¨  30  varsPtr  pointer  pointer to MPP globals
  2300.   ¨  34  dcePtr  pointer  pointer to DCE for .MPP
  2301.   ¨  38  portID  word  port number 
  2302.   ¨  40  configuration  long  configuration flags
  2303.   ¨  44  selfSend  word  nonzero if self-send is enabled
  2304.   ¨  46  netLo  word  low value of the network range
  2305.   ¨  48  netHi  word  high value of the network range
  2306.   ¨  50  ourAddr  long  local 24-bit AppleTalk address
  2307.   ¨  54  routerAddr  long  24-bit address of router
  2308.   ¨  58  numOfPHs  word  max number of protocol handlers
  2309.   ¨  60  numOfSkts  word  max number of static sockets
  2310.   ¨  62  numNBPEs  word  max concurrent NBP requests
  2311.   ¨  64  ntQueue  pointer  pointer to registered name queue
  2312.   ´  68  laLength  word  length in bytes of data link address
  2313.           (extended networks only)
  2314.   Æ  70  linkAddr  pointer  pointer to data link address buffer
  2315.           (extended networks only)
  2316.   Æ  74  zoneName  pointer  pointer to zone name buffer
  2317.  
  2318. The PGetAppleTalkInfo function returns information about the .MPP driver. If the
  2319. node on which your program is running happens also to be running AppleTalk
  2320. Internet Router software in the background, there may be more than one set of 
  2321. .MPP global variables in RAM. To make sure you are obtaining information about
  2322. the .MPP driver that handles application software, always use the
  2323. PGetAppleTalkInfo function rather than the Device Manager’s PBControl function.
  2324. If you are using assembly language, or want to use the PBControl function, you
  2325. must use a device driver reference number of –10 for the .MPP driver.
  2326.  
  2327. Parameters
  2328.  
  2329. ioResult
  2330. The result of the function. When you execute the function asynchronously, the
  2331. function sets this parameter to 1 and returns a function result of noErr as soon
  2332. as the function begins execution. When the function completes execution, it sets
  2333. the ioResult parameter to the actual result code. 
  2334.  
  2335. csCode
  2336. Routine selector, automatically set by the MPW interface. Always equal to
  2337. PGetAppleTalkInfo for this function.
  2338.  
  2339. version
  2340. The version number of the PGetAppleTalkInfo function you are calling. For
  2341. version number 53 of the .MPP driver, this number is always 1.
  2342.  
  2343. varsPtr
  2344. A pointer to the MPP global variables. The MPP global variables are discussed in
  2345. “Protocol Handlers and Socket Listeners” in Chapter 10 of Volume II.
  2346.  
  2347. dcePtr
  2348. A pointer to the device control entry (DCE) data structure for the .MPP driver.
  2349. The DCE is described in the Device Manager chapters of Volumes II and V.
  2350.  
  2351. portID
  2352. The port number for the .MPP driver. The port number is always 0 unless you are
  2353. requesting information for an .MPP driver being used by a router.
  2354.  
  2355. configuration
  2356. A 32-bit long word of configuration flags. The following flags are currently
  2357. defined:
  2358.  
  2359. Bit  Flag       Description
  2360. 31   SrvAdrBit  TRUE (1) if the routine that opened the .MPP driver requested a
  2361. server node number. Server node numbers are described in the AppleTalk Manager
  2362. of Volume V. This flag indicates only that the server-node number was requested,
  2363. not that it was returned. Some AppleTalk devices, such as EtherTalk, do not
  2364. honor a request for a server-node number.
  2365.  
  2366. 30   RouterBit  TRUE (1) if an AppleTalk Internet Router was loaded at system
  2367. startup (that is, there's a router operating on the same node as your
  2368. application). A router can be loaded but not active.
  2369.  
  2370. 15   ExtendedBit  TRUE (1) if the node is on an extended network.
  2371.  
  2372. 7    BadZoneHintBit  TRUE (1) if the zone name of the node you are on was not
  2373. the same as the zone name stored in parameter RAM (sometimes referred to as the
  2374. zone name hint) when the .MPP driver was opened. If the zone name hint is
  2375. invalid, then the AppleTalk Manager uses the default zone for the network.
  2376.  
  2377. 6    OneZoneBit  TRUE (1) if only one zone is assigned to your extended network
  2378. or if you are not on an extended network.
  2379.  
  2380. selfSend
  2381. This parameter is nonzero if the ability of a node to send packets to itself is
  2382. enabled. Use the PSetSelfSend function, described in the AppleTalk Manager
  2383. chapter of Volume V, to enable or disable this feature.
  2384.  
  2385. netLo
  2386. The low value of the range of network numbers on the local cable. Only extended
  2387. networks can have a range of network numbers. For a nonextended network, this
  2388. parameter returns the network number.
  2389.  
  2390. netHi
  2391. The high value of the range of network numbers on the local cable. Only extended
  2392. networks can have a range of network numbers. For a nonextended network, this
  2393. parameter returns the network number.
  2394.  
  2395. ourAddr
  2396. The 24-bit AppleTalk network address of the node you are on. The least
  2397. significant byte of the longword is the node ID. The middle 16 bits are the
  2398. network number. The most significant byte of the longword is reserved for use by
  2399. Apple Computer, Inc. 
  2400.  
  2401. routerAddr
  2402. The 24-bit AppleTalk network address of the last router from which your node
  2403. heard traffic. The least significant byte of the longword is the node ID. The
  2404. middle 16 bits are the network number. The most significant byte of the longword
  2405. is reserved for use by Apple Computer, Inc. You should always use this address
  2406. when you want to communicate with a router.
  2407.  
  2408. numOfPHs
  2409. The maximum number of protocol handlers that this .MPP driver allows.
  2410.  
  2411. numOfSkts
  2412. The maximum number of statically assigned sockets that this .MPP driver allows.
  2413. Statically assigned sockets are described in Inside AppleTalk.
  2414.  
  2415. numNBPEs
  2416. The maximum number of concurrent requests to NBP that this .MPP driver allows. 
  2417.  
  2418. ntQueue
  2419. A pointer to the first entry in the names table for the local node. You can use
  2420. NBP routines to look up and register names in the names table. The names table
  2421. is described in “Name-Binding Protocol” in Chapter 10 of Volume II.
  2422.  
  2423. laLength
  2424. When you call the PGetAppleTalkInfo function on a node on an extended network,
  2425. you use this parameter to specify the number of bytes of the data link address
  2426. the function should place in the buffer pointed to by the LinkAddr parameter. If
  2427. you request more bytes than the total number of bytes in the address, then the
  2428. function returns in the laLength parameter the actual number of bytes it placed
  2429. in the buffer. If the address is longer than the size of the buffer, then the
  2430. PGetAppleTalkInfo function fills the buffer and returns in the laLength
  2431. parameter the actual length of the address, not the number of bytes returned.
  2432. The function does not return an error when the buffer is too large or too small
  2433. for the address.
  2434.  
  2435. linkAddr
  2436. A pointer to a buffer for the data link address returned for extended networks
  2437. only. You use the laLength parameter to specify the number of bytes of the
  2438. address that you want placed in this buffer. You must allocate a buffer large
  2439. enough to hold the number of bytes you specify. Speficy NIL for this parameter
  2440. if you do not want the function to provide a data-link address.
  2441.  
  2442. zoneName
  2443. A pointer to a buffer into which the PGetAppleTalkInfo function places the local
  2444. node’s zone name. You must allocate a buffer of at least 33 bytes to hold this
  2445. data, or specify NIL for the ZoneName parameter if you do not want to obtain the
  2446. zone name. This field is returned only if the node is on an extended network.
  2447.  
  2448. Result codes
  2449. noErr  0  no error
  2450. _______________________________________________________________________________
  2451.  
  2452. æKY A…New…NBP…Wildcard…Character
  2453. æC »A New NBP Wildcard Character                                         AppleTalk Manager
  2454. _______________________________________________________________________________
  2455.  
  2456. The Name-Binding Protocol (NBP) allows the use of certain wildcard characters in
  2457. AppleTalk names. You can use a wildcard character in a call to the PLookupName
  2458. function, for example, to obtain names and addresses of all the entities in a
  2459. given zone. NBP now supports the following wildcard characters:
  2460.  
  2461. NBP Wildcard characters
  2462.  
  2463. =  All possible values. This character can be used alone instead of a name in
  2464.    the object or type fields.
  2465.  
  2466. *  This zone. This character can be used alone instead of the zone name for the 
  2467.    local zone only.
  2468.  
  2469. ≈   Any or no characters in this position. This character can be used to obtain
  2470.     matches for object or type fields. For example, pa≈l matches pal, paul, 
  2471.     paper ball, and so forth. You can use only one double tilde (≈) character in
  2472.     any string. Press option-x to type the double tilde character on a Macintosh
  2473.     keyboard. If you use the double tilde character alone, it has the same 
  2474.     meaning as the equal sign (=). Note that any node not running AppleTalk
  2475.     Phase 2 drivers will not recognize this character.
  2476.  
  2477. _______________________________________________________________________________
  2478.  
  2479. æKY The…LAP…Manager
  2480. æC »THE LAP MANAGER                                                      AppleTalk Manager
  2481. _______________________________________________________________________________
  2482.  
  2483. The LAP Manager is a set of operating system utilities that provide a standard
  2484. interface between the AppleTalk protocols and the various link access protocols,
  2485. such as EtherTalk (ELAP), TokenTalk (TLAP), and LocalTalk (LLAP). Because the
  2486. LAP Manager is running even when the .MPP driver is not open, the LAP Manager
  2487. maintains the AppleTalk Transition Queue. The LAP Manager also contains protocol
  2488. handlers for certain types of 802.2 packets. This section describes the
  2489. AppleTalk Transition Queue and the LAP Manager 802.2 protocol handler, tells you
  2490. how to add or remove an AppleTalk Transition Queue entry, and describes how to
  2491. attach or detach your own 802.2 protocol handler.
  2492.  
  2493. _______________________________________________________________________________
  2494.  
  2495. æKY The…AppleTalk…Transition…Queue
  2496. æC »The AppleTalk Transition Queue                                       AppleTalk Manager
  2497. _______________________________________________________________________________
  2498.  
  2499. At any given time there might be two or more applications running that use
  2500. AppleTalk. If one of these applications opens or closes the AppleTalk drivers,
  2501. the other AppleTalk applications are affected. To ensure that your application
  2502. is not adversely affected by such an event, your application can place an entry
  2503. in the AppleTalk Transition Queue. The AppleTalk drivers send a message to each
  2504. application that is listed in the AppleTalk Transition Queue each time a routine
  2505.  
  2506.   •   opens the .MPP driver
  2507.   •   closes the .MPP driver
  2508.   •   indicates that it intends to close the .MPP driver
  2509.   •   denies permission to close the .MPP driver
  2510.   •   cancels its intention to close the .MPP driver
  2511.  
  2512. Each of these events is referred to as an AppleTalk transition.
  2513.  
  2514. Because opening or closing the .MPP driver opens or closes the .ATP and .XPP
  2515. drivers as well, and bacause the .MPP driver must be open before an application
  2516. can open the .DSP driver, knowing the status of the .MPP driver is tantamount to
  2517. knowing the status of all AppleTalk drivers.
  2518.  
  2519. Because the .MPP driver is not necessarily open when the AppleTalk Transition
  2520. Queue must be called, the LAP Manager maintains the queue. Each entry in the
  2521. AppleTalk Transition Queue is defined by the ATQentry record type.
  2522.  
  2523. TYPE ATQentry = RECORD
  2524.    qLink:     ATQentryPtr;  {next queue entry}
  2525.    qType:     INTEGER;      {unused}
  2526.    CallAddr:  ProcPtr;      {pointer to your routine}
  2527. END;
  2528.  
  2529. ATQentryptr = ^ATQentry;
  2530.  
  2531. When you want to add an entry to the AppleTalk Transition Queue, you must create
  2532. an ATQentry record and give the LAP Manager a pointer to this record. The qLink
  2533. field is a pointer to the next queue entry. You should set this field to NIL;
  2534. the LAP Manager fills it in when an application adds another entry to the queue.
  2535. The qType field is not used, but is present to maintain consistency with other
  2536. operating system queues . The CallAddr field is a pointer to a routine that you
  2537. provide. Your routine must handle the AppleTalk transition routines described in
  2538. “How the AppleTalk Manager Calls Your AppleTalk Transition Queue Routine” later
  2539. in this chapter.
  2540.  
  2541. Because you allocate the memory for the AppleTalk Transition Queue entry, you
  2542. can add as many fields to the end of the entry as you wish for your own
  2543. purposes. Whenever your routine is called, the caller provides you with a
  2544. pointer to the queue entry so that you can have access to the information you
  2545. stored at the end of your queue entry.
  2546.  
  2547. _______________________________________________________________________________
  2548.  
  2549. æKY Adding…and…Removing…AppleTalk…Transition…Queue…Entries
  2550. æC »Adding and Removing AppleTalk Transition Queue Entries               AppleTalk Manager
  2551. _______________________________________________________________________________
  2552.  
  2553. There are three LAP Manager procedures you can use that are related to the
  2554. AppleTalk Transition Queue:
  2555.  
  2556.   •   The LAPAddATQ procedure adds an entry to the AppleTalk Transition Queue.
  2557.       You provide in the A0 register a pointer to an ATQentry record. The
  2558.       CallAddr field of the ATQentry record holds a pointer to your routine.
  2559.       The LAP Manager fills in the qLink field with a pointer to the next queue
  2560.       entry.
  2561.  
  2562.   •   The LAPRmvATQ procedure removes an entry from the AppleTalk Transition
  2563.       Queue. You provide in the A0 register a pointer to your queue entry.
  2564.  
  2565.   •   The LAPGetATQ procedure returns in the A1 register a pointer to the
  2566.       AppleTalk Transition Queue header.
  2567.  
  2568. Assembly-language note:  From assembly language, you call LAP Manager routines
  2569. by placing a routine selector in the D0 register and executing a JSR instruction
  2570. to an offset 2 bytes past the start of the LAP manager. Before you call the
  2571. LAPAddATQ or LAPRmvATQ routines, you must also place a pointer to your AppleTalk
  2572. Transition Queue entry in the A0 register. The LAPGetATQ routine returns a
  2573. pointer to the AppleTalk Transition Queue header in the A1 register. 
  2574. Here is an assembly-language call to a LAP Manager routine:
  2575.  
  2576. LAPMgrPtr   EQU  $B18  ;Entry point for LAP Manager
  2577. LAPMgrCall  EQU  2     ;Offset to LAP Manager routines
  2578. ATQEntry    EQU  *     ;AppleTalk Transition Queue entry
  2579. ...
  2580.  
  2581.     MOVEQ #Code,D0       ;Place routine selector in D0
  2582.     MOVE.L LAPMgrPtr,An  ;Put LAP Mgr entry pt in An
  2583.     MOVE.L ATQEntry,A0   ;Put ATQ entry in A0 (LAPAddATQ & LAPRmvATQ only)
  2584.     JSR  LAPMgrCall(An)  ;Jump to start of LAP Mgr routines
  2585.  
  2586. You can use LAP Manager routines to add an entry to the AppleTalk Transition
  2587. Queue, remove an entry from the queue, or obtain a pointer to the AppleTalk
  2588. Transition Queue header. See “Using the AppleTalk Transition Queue,” earlier in
  2589. this chapter, for a description of the queue and how to use it.
  2590.  
  2591. PROCEDURE LAPAddATQ (entryPtr: pointer);
  2592.  
  2593. On entry  D0: 23
  2594.           A0: pointer to ATQentry record
  2595.  
  2596. The LAPAddATQ procedure adds an entry to the AppleTalk Transition Queue. The
  2597. entryPtr parameter is a pointer to an ATQentry record. The ATQentry record
  2598. includes a pointer to the routine that AppleTalk calls when any routine opens or
  2599. closes the .MPP driver, or indicates that it intends to close the .MPP driver.
  2600. The ATQentry is described in “Using the AppleTalk Transition Queue” earlier in
  2601. this chapter.
  2602.  
  2603. PROCEDURE LAPRmvATQ (entryPtr: pointer);
  2604. \
  2605. On entry  D0: 24
  2606.           A0: pointer to ATQentry record
  2607.  
  2608. The LAPRmvATQ procedure removes an entry from the AppleTalk Transition Queue.
  2609. The entryPtr parameter is a pointer to an ATQentry record. 
  2610.  
  2611. PROCEDURE LAPGetATQ (VAR eqPtr: pointer);
  2612.  
  2613. On entry  D0: 25
  2614. On exit  A1: pointer to AppleTalk Transition Queue header
  2615.  
  2616. The LAPGetATQ procedure returns a pointer to the AppleTalk Transition Queue
  2617. header.
  2618. _______________________________________________________________________________
  2619.  
  2620. æKY Sending…Messages…to…the…AppleTalk…Transition…Queue
  2621. æC »Sending Messages to the AppleTalk Transition Queue                   AppleTalk Manager
  2622. _______________________________________________________________________________
  2623.  
  2624. Whereas it is unlikely that opening the .MPP driver will adversely affect
  2625. another program, an application should never close the .MPP driver, because
  2626. another program might be using it. Under certain circumstances, however, the
  2627. system might close the .MPP driver, provided no application objects. The system
  2628. uses the .MPP driver’s PATalkClosePrep function to inform each routine in the
  2629. AppleTalk Transition Queue that it intends to close the .MPP driver, giving each
  2630. routine in the queue the opportunity to deny permission to do so.
  2631.  
  2632. The system provides a pointer to a 255-byte buffer when it calls the
  2633. PATalkClosePrep function. If any routine in the AppleTalk Transition Queue
  2634. denies permission to close the .MPP driver, it places a name in the buffer and
  2635. returns control to the AppleTalk Manager. The name that the routine places in
  2636. the buffer should be the name of the application that placed the entry in the
  2637. queue. The PATalkClosePrep function then calls each routine in the AppleTalk
  2638. Transition Queue a second time to inform it that the request to close the .MPP
  2639. driver has been canceled. If any routine in the AppleTalk Transition Queue
  2640. denies permission to close the .MPP driver, the PATalkClosePrep function returns
  2641. the result code closeErr.
  2642.  
  2643. If any routine denies permission to close the .MPP driver, the system displays a
  2644. dialog box informing the user that another application is using the .MPP driver,
  2645. and showing the name that the AppleTalk Transition Queue routine placed in the
  2646. buffer. The dialog box gives the user the option of canceling the request to
  2647. close AppleTalk, or of closing AppleTalk anyway. 
  2648.  
  2649. Note:  If the user chooses to close AppleTalk despite the fact that an
  2650. application is using it, the system calls the MPPClose function. AppleTalk calls
  2651. each application in the AppleTalk Transition Queue again, this time informing it
  2652. that AppleTalk is about to close. In this case, your AppleTalk Transition Queue
  2653. routine must prepare for the imminent closing of AppleTalk; it cannot deny
  2654. permission to the MPPClose function.
  2655.   
  2656. FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  2657.  
  2658. Parameter block
  2659.   Æ  26  csCode  word  always PATalkClosePrep
  2660.   Æ      appName  pointer  buffer for name of application that denies request
  2661.  
  2662. The PATalkClosePrep function calls each routine listed in the AppleTalk
  2663. Transition Queue to request permission to close the .MPP driver. 
  2664. The routine that calls the PATalkClosePrep function must allocate a 255-byte
  2665. buffer and provide a pointer to it in the appName parameter. If a routine in the
  2666. AppleTalk Transition Queue denies permission to close the .MPP driver, that
  2667. routine places a name in the buffer pointed to by the appName parameter, and the
  2668. AppleTalk Manager calls each routine in the AppleTalk Transition Queue a second
  2669. time to inform it that the request to close the .MPP driver has been canceled.
  2670. The PATalkClosePrep function then returns the result code closeErr, indicating
  2671. that the calling routine may not close the .MPP driver. The csCode parameter is
  2672. a routine selector; it is always equal to PATalkClosePrep for this function.
  2673.  
  2674. Result codes
  2675. noErr       0  no error
  2676. closeErr  –24  permission to close .MPP driver was denied
  2677.  
  2678. The system can use the PCancelATClosePrep function to undo the effects of the
  2679. PATalkClosePrep function. The system uses this function, for example, if some
  2680. condition prevents it from closing the .MPP driver even though each routine
  2681. listed in the AppleTalk Transition Queue gave permission to close it. When the
  2682. system calls the PCancelATClosePrep function, the AppleTalk Manager calls each
  2683. routine in the AppleTalk Transition Queue to inform it that the request to close
  2684. the .MPP driver has been canceled.
  2685.  
  2686. FUNCTION PCancelATClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  2687.  
  2688. Parameter block
  2689.   Æ  26  csCode  word  always PCancelATClosePrep 
  2690.  
  2691. The PCancelATClosePrep function undoes the effects of the PATalkClosePrep
  2692. function. The PCancelATClosePrep function calls each routine in the AppleTalk
  2693. Transition Queue to inform it that the request to close the .MPP driver has been
  2694. canceled. 
  2695.  
  2696. The operating system uses this function, for example, if some condition prevents
  2697. it from closing the .MPP driver even though each routine listed in the AppleTalk
  2698. Transition Queue gave permission to close it. 
  2699.  
  2700. The csCode parameter is a routine selector, always equal to PCancelATClosePrep
  2701. for this function.
  2702.  
  2703. Result codes
  2704. noErr  0  no error
  2705. _______________________________________________________________________________
  2706.  
  2707. æKY How…the…AppleTalk…Manager…Calls…Your…Transition…Queue…Routine
  2708. æC »How the AppleTalk Manager Calls Your Transition Queue Routine        AppleTalk Manager
  2709. _______________________________________________________________________________
  2710.  
  2711. When you have used the LAPAddATQ function to add an entry to the AppleTalk
  2712. Transition Queue, the AppleTalk Manager calls your routine when any of the
  2713. following AppleTalk transitions occurs:
  2714.  
  2715.   •   A routine opens the .MPP driver. 
  2716.   •   A routine closes the .MPP driver. 
  2717.   •   A routine calls the ATalkClosePrep function. 
  2718.   •   One of the routines in the AppleTalk Transition Queue denies permission
  2719.       for the routine that called the ATalkClosePrep function to close
  2720.       AppleTalk, or a routine executes the PCancelATClosePrep function.
  2721.  
  2722. When the AppleTalk Manager calls your AppleTalk Transition Queue routine, the
  2723. first item on the stack (after the return address) is a routine selector. There
  2724. is one routine selector for each type of transition:
  2725.  
  2726. Routine selector  Transition
  2727.   0               .MPP driver opened
  2728.   2               .MPP driver about to close
  2729.   3                ATalkClosePrep function has been called
  2730.   4                Closing of .MPP driver has been canceled
  2731.  
  2732. The interface between the AppleTalk Transition Queue and your routine follows
  2733. the conventions of the C language: Your routine must preserve all registers
  2734. except D0, D1, D2, A0 and A1; all parameters are passed on the stack as long
  2735. words.
  2736.  
  2737. Note:  Because the number of parameters that an AppleTalk Transition Queue
  2738. routine must read off the stack varies with the routine selector, and because
  2739. the routine must be able to place a value in the D0 register, you cannot use
  2740. Pascal to write an AppleTalk Transition Queue routine.
  2741.  
  2742. When an application calls the MPPOpen function to open the .MPP driver, the
  2743. AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
  2744. after it opens the .MPP driver. When the AppleTalk Manager calls your AppleTalk
  2745. Transition Queue routine to tell it that the .MPP driver has been opened, the
  2746. stack looks like this:
  2747.  
  2748. SP Æ   Return address (4 bytes)
  2749.        Routine selector; 0 when .MPP opens (4 bytes)
  2750.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2751.        Pointer to Device Manager’s parameter block (4 bytes)
  2752.        previous contents
  2753.  
  2754. If the .MPP driver is already open and a routine executes the MPPOpen function,
  2755. the AppleTalk Manager does not call the routines in the AppleTalk Transition
  2756. Queue.
  2757.  
  2758. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2759. Queue to get access to any fields at the end of the queue entry that you
  2760. allocated for your own use. The last item on the stack is a pointer to the start
  2761. of the Device Manager extended parameter block used by the routine that opened
  2762. the .MPP driver. This pointer is provided for your information only; you must
  2763. not change any of the fields in this parameter block. 
  2764.  
  2765. Your AppleTalk Transition Queue routine can perform any tasks you wish in
  2766. response to the notification that the .MPP driver has been opened, such as using
  2767. NBP to register a name on the internet. 
  2768.  
  2769. When any routine calls the MPPClose function to close the .MPP driver, the
  2770. AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
  2771. before the .MPP driver closes. When the AppleTalk Manager calls your routine to
  2772. tell it that the .MPP driver is about to close, the stack looks like this:
  2773.  
  2774.  
  2775. SP Æ  Return address (4 bytes)
  2776.        Routine selector; 2 when .MPP is about to close (4 bytes)
  2777.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2778.        previous contents
  2779.  
  2780. If the .MPP driver is already closed and a routine executes the MPPClose
  2781. function, the AppleTalk Manager does not call the routines in the AppleTalk
  2782. Transition Queue.
  2783.  
  2784. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2785. Queue to get access to any fields at the end of the queue entry that you
  2786. allocated for your own use.
  2787.  
  2788. Your routine can perform any tasks you wish to prepare for the imminent closing
  2789. of AppleTalk, such as ending a session with a remote terminal and informing the
  2790. user that the connection is being closed. You must return control to the
  2791. AppleTalk Manager as quickly as possible. When the AppleTalk Manager calls your
  2792. routine with a routine selector of 2, you cannot prevent the .MPP driver from
  2793. closing.
  2794.  
  2795. When a routine calls the ATalkClosePrep function to inform the AppleTalk Manager
  2796. that it wants to close the .MPP driver, the AppleTalk Manager calls every
  2797. routine listed in the AppleTalk Transition Queue to request permission to close
  2798. the .MPP driver. When the AppleTalk Manager calls your routine to request
  2799. permission to close the .MPP driver, the stack looks like this:
  2800.  
  2801.  
  2802. SP Æ  Return address (4 bytes)
  2803.        Routine selector; 3 to ask permission to close .MPP (4 bytes)
  2804.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2805.        Pointer to pointer to name of client (4 bytes)
  2806.        previous contents
  2807.  
  2808. Your routine can return either a longword of zeros in the D0 register,
  2809. indicating that it accepts the request to close, or a nonzero value in the D0
  2810. register, indicating that it denies the request to close. 
  2811. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2812. Queue to get access to any fields at the end of the queue entry that you
  2813. allocated for your own use.
  2814.  
  2815. The last parameter on the stack is a pointer to the clientName field (offset 28)
  2816. in the .MPP driver parameter block that was used by the routine that called the
  2817. PATalkClosePrep function. This field contains a pointer to a 255-byte buffer. If
  2818. you intend to deny the request to close AppleTalk, you should place a string in
  2819. this buffer containing the name of your application. The routine that called the
  2820. PATalkClosePrep function can then display a dialog box telling the user the name
  2821. of the application that is currently using AppleTalk.
  2822.  
  2823. Because the AppleTalk Manager calls your routine again (with the routine
  2824. selector set to 2) before the .MPP driver actually closes, it is not necessary
  2825. for your routine to do anything other than grant or deny permission in response
  2826. to being called with the routine selector set to 3. However, you might want to
  2827. prohibit the users from opening new sessions or establishing new connections
  2828. while you are waiting for the .MPP driver to close.
  2829.  
  2830. When a routine calls the PCancelATClosePrep function to cancel the effects of
  2831. the PATalkClosePrep function, or when any routine in the AppleTalk Transition
  2832. Queue denies permission for the .MPP driver to close, the AppleTalk Manager
  2833. calls every routine listed in the AppleTalk Transition Queue to inform it that
  2834. the request to close the .MPP driver has been canceled. When the AppleTalk
  2835. Manager calls your AppleTalk Transition Queue routine to cancel a request to
  2836. close the .MPP driver, the stack looks like this:
  2837.  
  2838.  
  2839. SP Æ  Return address (4 bytes)
  2840.        Routine selector; 4 to cancel a close (4 bytes)
  2841.        Pointer to AppleTalk Transition Queue entry (4 bytes)
  2842.        previous contents
  2843.  
  2844. You can use the pointer to your routine’s entry in the AppleTalk Transition
  2845. Queue to get access to any fields at the end of the queue entry that you
  2846. allocated for your own use.
  2847.  
  2848. If your routine performed any tasks to prepare for the closing of AppleTalk, it
  2849. should reverse their effects when it is called with the routine selector set to
  2850. 4.
  2851.  
  2852. Listing 29-1 illustrates the use of the AppleTalk Transition Queue. It defines a
  2853. routine that AppleTalk is to call when an AppleTalk transition occurs. This
  2854. routine first checks the stack to determine why it is being called, and then
  2855. acts accordingly. If the routine selector indicates that the .MPP driver has
  2856. just opened, the listing uses NBP to register a name on the internet. If the
  2857. .MPP driver is about to close, the routine calls ADSP to close the session and
  2858. displays a dialog box informing the user that the session is being closed. If
  2859. some application is asking permission to close the .MPP driver, the routine
  2860. checks to see if your application has an open ADSP session. If your application
  2861. has a current open ADSP session, the routine places the name of your application
  2862. in the buffer provided by the client that called the PATalkClosePrep function,
  2863. and places a 0 in the D0 register. If your application has no open ADSP session,
  2864. the routine places a 1 in the D0 register. If AppleTalk is canceling a request
  2865. to close the .MPP driver, the routine terminates without further action. 
  2866. Listing 29-1 also defines an entry to the AppleTalk Transition Queue that points
  2867. to the routine, and calls the LAPAddATQ procedure to add this entry to the
  2868. queue. 
  2869.  
  2870. Listing 29-1.  Using the AppleTalk Transition Queue (TO BE PROVIDED)
  2871.  
  2872. _______________________________________________________________________________
  2873.  
  2874. æKY The…LAP…Manager…802.2…Protocol
  2875. æC »The LAP Manager 802.2 Protocol                                       AppleTalk Manager
  2876. _______________________________________________________________________________
  2877.  
  2878. The Institute of Electrical and Electronics Engineers (IEEE) has defined a
  2879. series of communication protocols for use on a variety of networks. At the
  2880. hardware and signaling level, these protocols include the 802.3 Ethernet
  2881. protocol, the 802.4 Token Bus protocol, and the 802.5 Token Ring protocol. At
  2882. the link access level, these protocols are all handled by another IEEE protocol,
  2883. the 802.2 protocol. The AppleTalk LAP Manager includes two routines that allow
  2884. you to attach and detach protocol handlers for 802.2 Type 1 data packets: the
  2885. L802Attach and L802Detach routines. You can write an application that reads
  2886. 802.2 Type 1 data packets, and use the L802Attach routine to install your
  2887. application as a client of the LAP Manager. The ANSI/IEEE standards for the 802
  2888. protocols are published by the Institute of Electrical and Electronics
  2889. Engineers.
  2890.  
  2891. The first 14 bytes of a packet sent or received by the .ENET driver are the
  2892. header. The first 12 bytes consist of the destination and source data link
  2893. addresses (such as the Ethernet hardware addresses). If the value of the last
  2894. two bytes in the header is greater than 1500, then the .ENET driver treats that
  2895. field as an Ethernet protocol type discriminator. See “The .ENET Driver,” later
  2896. in this chapter, for more information on Ethernet protocols. If the value of the
  2897. last two bytes in the header is less than 1500, then the packet is an 802.3
  2898. protocol packet and the .ENET driver passes it to the LAP Manager.
  2899.  
  2900. The LAP Manager receives the entire 802.3 packet from the .ENET driver. The
  2901. first three bytes of the 802.3 data constitues the header for the 802.2
  2902. protocol. The first byte of the 802.2 header is known as the destination service
  2903. access point (DSAP). If the DSAP type field is equal to $AA, then the first five
  2904. bytes of the 802.2 data constitutes a protocol discriminator known as the
  2905. subnetwork access protocol (SNAP) type. If the SNAP type field is $00000080F3,
  2906. indicating the AppleTalk Address Resolution Protocol (AARP), then the next four
  2907. bytes of the 802.2 data constitutes a third type field, the AARP packet type.
  2908. AARP is discussed in Inside AppleTalk.
  2909.  
  2910. The following data packet header, for example, indicates an Ethernet packet
  2911. containing AppleTalk data. The .ENET driver would deliver this packet to the
  2912. AppleTalk Phase 1 device drivers.
  2913.  
  2914. 02608C010203 02608C040506 809B
  2915.  
  2916. By contrast, the following data packet header indicates an 802.3 packet
  2917. containing AppleTalk data. The .ENET driver would deliver this packet to the
  2918. AppleTalk Phase 2 LAP Manager
  2919.  
  2920. 02608C010203 02608C040506 0060 AA AA 03 080007809B
  2921.  
  2922. Similarly, the following data packet header indicates an 802.3 packet to be
  2923. delivered to the EtherTalk AARP handler:
  2924.  
  2925. 02608C010203 02608C040506 0060 AA AA 03 00000080F3 0001809B
  2926.  
  2927. When you call the L802Attach function, you provide a pointer to your protocol
  2928. handler, the reference number of the .ENET driver, and a pointer to a string
  2929. containing one or more type fields. The type fields indicate the DSAP value and
  2930. any other protocol type fields (such as the SNAP type and the AARP type). The
  2931. LAP Manager delivers to your protocol handler any 802.2 data packets that have
  2932. the protocol type you specify. 
  2933. _______________________________________________________________________________
  2934.  
  2935. æKY Attaching…and…Detaching…802.2…Protocol…Handlers
  2936. æC »Attaching and Detaching 802.2 Protocol Handlers                      AppleTalk Manager
  2937. _______________________________________________________________________________
  2938.  
  2939. You can attach to the LAP Manager your own protocol handler for 802.2 protocols.
  2940. The LAP Manager has permanent handlers for certain types of EtherTalk packets.
  2941. You cannot replace or override the permanent LAP Manager protocol handlers.
  2942.  
  2943. FUNCTION L802Attach (Eref: word; handlerPtr: procptr; ProtType: pointer) :
  2944. OSErr;
  2945.  
  2946.  
  2947. On entry  D0: 21
  2948.           D2: reference number of .ENET driver
  2949.           A0: pointer to your protocol handler
  2950.           A1: pointer to protocol specification
  2951.  
  2952. On exit   D0: nonzero if error
  2953.  
  2954. The L802Attach function attaches to the LAP Manager a protocol handler for a
  2955. specific IEEE 802.2 protocol type.
  2956.  
  2957. The Eref parameter is the reference number of the .ENET driver that was returned
  2958. by the OpenSlot function when you or somone else opened the .ENET driver. If you
  2959. are not using the .ENET driver or a driver that uses the same interface as the
  2960. .ENET driver, you cannot use the L802Attach function. The handlerPtr parameter
  2961. is a pointer to your protocol handler.
  2962.  
  2963. The ProtType parameter is a pointer to the protocol type specification for this
  2964. protocol handler. The protocol type specification consists of one or more
  2965. protocol type fields, each preceded by a length byte. The LAP Manager reads the
  2966. protocol type fields in the 802.2 data packet header to determine to which
  2967. protocol handler (if any) to deliver the packet. The first type field in your
  2968. protocol specification is 1 byte long and is known as the destination service
  2969. access point (DSAP). If the DSAP type field is equal to $AA, then the protocol
  2970. type specification can contain a second type field, the 5-byte subnetwork access
  2971. protocol (SNAP) type. If the SNAP type field is $00000080F3, indicating the
  2972. AppleTalk Address Resolution Protocol (AARP), then the protocol type
  2973. specification can contain a third type field, the 4-byte AARP protocol type.
  2974. Terminate the list of protocol type fields with a byte of zeros.
  2975.  
  2976. The following protocol type specification, for example, indicates an 802.3
  2977. packet containing AppleTalk data. The .ENET driver would deliver this packet to
  2978. the AppleTalk Phase 2 LAP Manager. The first byte, $01, is the length byte for
  2979. the first protocol type field (the DSAP type field), $AA. The third byte, $05,
  2980. is the length byte for the next protocol type field, the SNAP. The final byte 
  2981. ($00) terminates the type specification.
  2982.  
  2983. 01 AA 05 08 00 07 80 9B 00
  2984.  
  2985. The following protocol type specification indicates an 802.3 packet to be
  2986. delivered to the EtherTalk AARP handler: Notice that the SNAP field is followed
  2987. by an additional type field, the AARP protocol type.
  2988.  
  2989. 01 AA 05 00 00 00 80 F3 04 00 01 80 9B 00
  2990.  
  2991. See the ANSI/IEEE standard 802.2 for more information about 802.2 protocols, and
  2992. Inside AppleTalk for more information about AARP.
  2993.  
  2994. Result codes
  2995. noErr  0  no error
  2996.  
  2997. FUNCTION L802Detach (Eref: word; ProtType: pointer) : OSErr;
  2998.  
  2999. On entry  D0: 22
  3000.           D2: reference number of .ENET driver
  3001.           A1: pointer to protocol specification
  3002.  
  3003. On exit   D0: nonzero if error
  3004.  
  3005. The L802Detach function detaches from the LAP Manager a protocol handler for a
  3006. specific IEEE 802.2 protocol type.
  3007.  
  3008. The Eref parameter is the reference number of the .ENET driver that was returned
  3009. by the OpenSlot function when you or somone else opened the .ENET driver. The
  3010. handlerPtr parameter is a pointer to your protocol handler.
  3011.  
  3012. The ProtType parameter is a pointer to the protocol type specification for this
  3013. protocol handler. You must specify exactly the same protocol type as you
  3014. specified for the L802Attach function when you attached the protocol handler.
  3015.  
  3016. Result codes
  3017. noErr  0  no error
  3018. _______________________________________________________________________________
  3019.  
  3020. æKY AppleTalk…Data…Stream…Protocol…(ADSP)
  3021. æC »APPLETALK DATA STREAM PROTOCOL (ADSP)                                AppleTalk Manager
  3022. _______________________________________________________________________________
  3023.  
  3024. One of the significant new features of AppleTalk introduced with AppleTalk Phase
  3025. 2 is the AppleTalk Data Stream Protocol (ADSP), which provides a full-duplex
  3026. data stream connection between two nodes in the AppleTalk internet. Like the
  3027. AppleTalk Session Protocol, Printer Access Protocol, and AppleTalk Transaction
  3028. Protocol, ADSP uses the Datagram Delivery Protocol to send its data over the
  3029. internet. Therefore, even though ADSP appears to its clients to handle data as a
  3030. stream of bytes, the data is actually transmitted and received by DDP in
  3031. packets. ADSP takes advantage of this fact by including control and status
  3032. information in the DDP packet header. You can use the .DSP driver functions
  3033. described in “.DSP Driver Functions,” later in this chapter, to control an ADSP
  3034. connection. The 
  3035. .DSP driver takes care of implementation of the ADSP protocol for you. To use 
  3036. ADSP, you must have the file named 'ADSP' in your system folder.
  3037.  
  3038. Every ADSP connection is between two sockets in the AppleTalk internet. Each
  3039. socket can establish simultaneous ADSP connections with several other sockets,
  3040. but there can be only one ADSP connection between any two sockets at one time.
  3041. When a pair of sockets establishes an ADSP connection, each socket client
  3042. initializes and maintains a certain amount of control and state information that
  3043. it uses for error checking and to synchronize communication with the other
  3044. socket client. 
  3045.  
  3046. The combination of a socket and the ADSP information maintained by the socket
  3047. client is referred to as a connection end. When two connection ends establish
  3048. communication, the connection is considered an open connection. When both
  3049. connection ends terminate the link and dispose of the connection information
  3050. each maintains, the connection is considered a closed connection. If one
  3051. connection end is established but the other connection end is unreachable or has
  3052. disposed of its connection information, the connection is considered a half-open
  3053. connection. No communication can occur over a half-open or closed connection. To
  3054. prevent a half-open connection from tying up resources, ADSP automatically
  3055. closes any half-open connection that cannot reestablish communications within
  3056. two minutes.
  3057.  
  3058. _______________________________________________________________________________
  3059.  
  3060. æKY Using…ADSP
  3061. æC »Using ADSP                                                           AppleTalk Manager
  3062. _______________________________________________________________________________
  3063.  
  3064. You can use the AppleTalk Data Stream Protocol to implement a data stream
  3065. connection between any two sockets on the internet. (Note that although there
  3066. can be only one ADSP connection between any two sockets, a single socket can
  3067. maintain connections with several other sockets.) This section describes how to
  3068. open, maintain, and close a connection between two sockets on an internet. It
  3069. also describes how to establish and use a connection listener; that is, a
  3070. connection end that waits passively to receive a connection request and then
  3071. passes the connection request on to its client, the connection server. Finally,
  3072. this section describes how to write a routine that ADSP calls when your
  3073. connection end receives an unsolicited connection event. 
  3074. _______________________________________________________________________________
  3075.  
  3076. æKY The…ADSP…Connection…Control…Block
  3077. æC »The ADSP Connection Control Block                                    AppleTalk Manager
  3078. _______________________________________________________________________________
  3079.  
  3080. When you establish an ADSP connection end, you must allocate a nonrelocatiable
  3081. block of memory for, and provide a pointer to, a data structure known as a
  3082. connection control block (CCB). The CCB is used by ADSP to store state
  3083. information about the connection end. You may read the fields in the CCB to
  3084. obtain information about the connection end, but you are not allowed to write to
  3085. any of the fields except one, the userFlags field. The connection control block
  3086. requires 242 bytes, and is defined by the TRCCB record.
  3087.  
  3088. TPCCB = ^TRCCB;
  3089.  
  3090. TRCCB = PACKED RECORD
  3091.   ccbLink:        TPCCB;                        {link to next CCB}
  3092.   refNum:         INTEGER;                      {user reference number}
  3093.   state:          INTEGER;                      {state of the connection end}
  3094.   userFlags:      Byte;                         {user flags for connection}
  3095.   localSocket:    Byte;                         {local socket number}
  3096.   remoteAddress:  AddrBlock;                    {remote end internet address}
  3097.   attnCode:       INTEGER;                      {attention code received}
  3098.   attnSize:       INTEGER;                      {size of attention data}
  3099.   attnPtr:        Ptr;                          {pointer to attention data}
  3100.   reserved:       PACKED ARRAY [1..220] OF Byte {reserved for use by ADSP}
  3101. END;
  3102.  
  3103. The internet address of the remote connection end is defined in the TRCCB record
  3104. by an AddrBlock record:
  3105.  
  3106. AddrBlock = PACKED RECORD
  3107.   aNet:     INTEGER;  {network number}
  3108.   aNode:    Byte;     {node ID}
  3109.   aSocket:  Byte;     {socket number}
  3110. END;
  3111.  
  3112. Field descriptions
  3113.  
  3114. ccbLink
  3115. Pointer to the next CCB. For use by ADSP only.
  3116.  
  3117. refnum
  3118. The reference number of the connection end. This number is assigned by ADSP when
  3119. you establish the connection end.
  3120.  
  3121. state
  3122. The state of the connection end, as follows:
  3123.  
  3124. State       Value  Meaning
  3125. sListening  1      Socket is a connection listening socket; that is, a socket
  3126. that accepts ADSP requests to open connections and passes them on to a socket
  3127. client. Ordinarily used only by servers.
  3128.  
  3129. sPassive    2  Socket client is inactive but capable of accepting an ADSP
  3130. request to open a connection. Unlike a connection listening socket, which passes
  3131. the open-connection request on to a routine that can establish the connection on
  3132. any socket, a socket client in the sPassive state can accept an open-connection
  3133. request only to establish itself as a connection end.
  3134.  
  3135. sOpening    3  Socket client has sent an open-connection request and is waiting
  3136. for acknowledgment.
  3137.  
  3138. sOpen       4  Connection is open.
  3139.  
  3140. sClosing    5  Socket client has requested that ADSP close the connection, and
  3141. ADSP is sending data or waiting for acknowledgement of data it has sent before
  3142. closing the connection. 
  3143.  
  3144. sClosed     6  Either connection end or ADSP has closed the connection.
  3145.  
  3146. userFlags
  3147. Flags that indicate an unsolicited connection event has occurred. An unsolicited
  3148. connection event is an event initiated by ADSP or the remote connection end that
  3149. is not in response to any .DSP function that you executed.  
  3150.  
  3151. Each time an unsolicited connection event occurs, ADSP sets a flag in the
  3152. userFlags field of the CCB and calls the routine you specified in the
  3153. userRoutine parameter to the dspInit command (if any). The user routine must
  3154. read the userFlags field and then clear the flag to 0. ADSP cannot notify your
  3155. routine of future events unless you clear the flag after each event.
  3156.  
  3157.  
  3158. ADSP recognizes four types of unsolicited connection events, one corresponding
  3159. to each of the flags in this field. The events and flags are defined as follows,
  3160. where bit 7 is the most significant bit:
  3161.  
  3162. Event    Flag Bit  Meaning
  3163. eClosed     7      ADSP has been informed by the remote connection end that the
  3164. remote connection end has closed the connection. 
  3165.  
  3166. eTearDown   6      ADSP has determined that the remote connection end is not
  3167. responding, and so has closed the connection. 
  3168.  
  3169. eAttention  5      ADSP has received an attention message from the remote
  3170. connection end. 
  3171.  
  3172. eFwdReset   4      ADSP has received a forward reset command from the remote
  3173. client end, has discarded all ADSP data not yet delivered— including the data in
  3174. the local client end’s receive queue—and has resynchronized the connection. 
  3175.  
  3176. none        3–0    Reserved
  3177.  
  3178. localSocket
  3179. The socket number through which DDP transmits and receives the ADSP packets.
  3180.  
  3181. remoteAddress
  3182. The internet address of the socket used by the remote connection end.
  3183.  
  3184. attnCode
  3185. The attention code received by ADSP when the remote connection end sends an
  3186. attention message.
  3187.  
  3188. attnSize
  3189. The size of the attention message received by ADSP when the remote connection
  3190. end sends an attention message.
  3191.  
  3192. attnPtr
  3193. A pointer to a buffer containing the attention message received by ADSP from the
  3194. remote connection end.
  3195.  
  3196. reserved
  3197. A data buffer reserved for use by ADSP.
  3198.  
  3199. _______________________________________________________________________________
  3200.  
  3201. æKY The….DSP…Parameter…Block
  3202. æC »The .DSP Parameter Block                                             AppleTalk Manager
  3203. _______________________________________________________________________________
  3204.  
  3205. The .DSP commands use the AppleTalk preferred interface. Each .DSP command
  3206. includes a pointer to a parameter block that includes all of the parameters
  3207. needed by that command. 
  3208.  
  3209. The .DSP parameter block is defined by the DSPParamBlock record.
  3210.  
  3211. DSPParamBlock = PACKED RECORD
  3212.   qLink:   QElemPtr;  {next queue entry}
  3213.   qType:   INTEGER;  {queue type}
  3214.   ioTrap:   INTEGER;  {routine trap}
  3215.   ioCmdAddr:   Ptr;  {routine address}
  3216.   ioCompletion:   ProcPtr;  {completion routine}
  3217.   ioResult:   OsErr;  {result code}
  3218.   ioNamePtr:   StringPtr;  {used only for Open routine}
  3219.   ioVRefNum:   INTEGER;  {volume reference number}
  3220.   ioCRefNum:   INTEGER;  {driver reference number}
  3221.   csCode:   INTEGER;  {primary command code}
  3222.   qStatus:  LONGINT;  {reserved for ADSP}
  3223.   ccbRefNum:  INTEGER;  {CCB reference number}
  3224.  
  3225.   CASE INTEGER OF
  3226.     dspInit,
  3227.     dspCLInit:
  3228.     (
  3229.       ccbPtr:  TPCCB;  {pointer to CCB}
  3230.       userRoutine:  ProcPtr;  {pointer to user routine}
  3231.       sendQSize:  INTEGER;  {size of send queue}
  3232.       sendQueue:  Ptr;  {pointer to send queue}
  3233.       recvQSize:  INTEGER;  {size of receive queue}
  3234.       recvQueue:  Ptr;  {pointer to receive queue}
  3235.       attnPtr:  Ptr;  {pointer to attention-message buffer}
  3236.       localSocket:  Byte;  {local socket number}
  3237.     );
  3238.  
  3239.     dspOpen,
  3240.     dspCLListen,
  3241.     dspCLDeny:
  3242.      (
  3243.       localCID:  INTEGER;  {local connection ID}
  3244.       remoteCID:  INTEGER;  {remote connection ID}
  3245.       remoteAddress:  AddrBlock;  {remote internet address}
  3246.       filterAddress:  AddrBlock;  {address filter}
  3247.       sendSeq:  LONGINT;  {send sequence number}
  3248.       sendWindow:  INTEGER;  {size of remote buffer}
  3249.       recvSeq:  LONGINT;  {receive sequence number}
  3250.       attnSendSeq:  LONGINT;  {attention send seq number}
  3251.       attnRecvSeq:  LONGINT;  {attention receive seq num}
  3252.       ocMode:  Byte;  {connection opening mode}
  3253.       ocInterval:  Byte;  {interval bet open requests}
  3254.      ocMaximum:Byte;{retries of open conn req}
  3255.      );
  3256.  
  3257. dspClose,
  3258. dspRemove:
  3259.     (
  3260.       abort:  Byte;  {abort send requests}
  3261.     );
  3262.  
  3263. dspStatus:
  3264.     (
  3265.       statusCCB:  TPCCB;  {pointer to CCB}
  3266.       sendQPending:  INTEGER;  {bytes waiting in send queue}
  3267.       sendQFree:  INTEGER;  {available send-queue buffer}
  3268.       recvQPending:  INTEGER;  {bytes in receive queue}
  3269.       recvQFree:  INTEGER;  {avail receive-queue buffer}
  3270. )
  3271.  
  3272.     dspRead,
  3273.     dspWrite:
  3274.     (
  3275.       reqCount:  INTEGER;  {requested number of bytes}
  3276.       actCount:  INTEGER;  {actual number of bytes}
  3277.       dataPtr:  Ptr;  {pointer to data buffer}
  3278.       eom:  Byte;  {1 if end of message}
  3279.       flush:  Byte;  {1 to send data now}
  3280.     )
  3281.  
  3282. dspAttention:
  3283.     (
  3284.       attnCode:  INTEGER;  {client attention code}
  3285.       attnSize:  INTEGER;  {size of attention data}
  3286.       attnData:  Ptr;  {pointer to attention data}
  3287.       attnInterval:  Byte;  {reserved}
  3288.     )
  3289.  
  3290. dspOptions:
  3291.     (
  3292.       sendBlocking: INTEGER;  {send-blocking threshold}
  3293.       sendTimer:    Byte;     {reserved}
  3294.       rtmtTimer:    Byte;     {reserved}
  3295.       badSeqMax:    Byte;     {retransmit advice threshold}
  3296.       useCheckSum:  Byte;     {DDP checksum for packets}
  3297.     )
  3298.  
  3299.     dspNewCID:
  3300.     (
  3301.       newCID:  INTEGER;  {new connection ID}
  3302.     )
  3303. END;
  3304.  
  3305. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
  3306. in by the Device Manager; your application should not have to set or read these
  3307. parameters. The ioResult parameter returns the result of the function; in the
  3308. case that you call the function asynchronously, the Device Manager sets this
  3309. field to 1 as soon as you call the function, and changes the field to the actual
  3310. result code when the function completes execution. The ioCompletion parameter is
  3311. a pointer to a completion routine that you can provide; the Device Manager calls
  3312. your completion routine when it completes execution of the PBControl function.
  3313. If you are not providing a completion routine, specify NIL for this field. The
  3314. ioCRefNum and csCode fields specify the driver and the command to be executed;
  3315. you must fill in the csCode field. 
  3316.  
  3317. The qStatus field is reserved for use by ADSP. The ccbRefNum field is a
  3318. reference number for the connection control block. The CCB reference number is
  3319. returned by ADSP in response to the dspInit command. You must specify this
  3320. number as a parameter to every .DSP driver routine you call subsequently.
  3321.  
  3322. The remaining parameters are used only for specific commands; each of these
  3323. parameters is described in “.DSP Driver Commands” later in this chapter.
  3324.  
  3325. _______________________________________________________________________________
  3326.  
  3327. æKY Opening…and…Maintaining…an…ADSP…Connection
  3328. æC »Opening and Maintaining an ADSP Connection                           AppleTalk Manager
  3329. _______________________________________________________________________________
  3330.  
  3331. To use ADSP to establish and maintain a connection between a socket on your
  3332. local node and a remote socket, use the following procedure:
  3333.  
  3334. 1.  Use the MPPOpen command to open the .MPP driver and then use the OpenDriver
  3335. command to open the .DSP driver. The OpenDriver routine returns the reference
  3336. number for the .DSP driver; you must supply this reference number each time you
  3337. call the .DSP driver.
  3338.  
  3339. 2.  Allocate nonrelocatable memory for a connection control block, send and
  3340. receive queues, and an attention message buffer. If you need to allocate the
  3341. memory dynamically while the program is running, use the NewPtr routine.
  3342. Otherwise, the way in which you allocate the memory depends on the compiler you
  3343. are using (the program listing at the end of this section shows how it’s done in
  3344. Pascal). The memory that you allocate becomes the property of ADSP when you call
  3345. the dspInit command to establish a connection end. You cannot write any data to
  3346. this memory except by calling ADSP, and you must ensure that the memory remains
  3347. locked until you call the dspRemove command to eliminate the connection end.
  3348.  
  3349. The connection control block is 242 bytes. The attention message buffer must be
  3350. 570 bytes. When you send bytes to a remote connection end, ADSP stores the bytes
  3351. in a buffer called the send queue. It keeps the bytes you sent in the send queue
  3352. until the remote connection end acknowledges their receipt, so that they are
  3353. available to be retransmitted if necessary. When the local connection end
  3354. receives bytes, it stores them in a buffer called the receive queue until you
  3355. read them. The sizes you need for the send and receive queues depend on the
  3356. lengths of the messages being sent. 
  3357.  
  3358. ADSP does not transmit data from the remote connection end until there is room
  3359. for it in your receive queue. If your send or receive queues are too small, they
  3360. limit the speed with which you can transmit and receive data. A queue size of
  3361. 600 bytes should work well for most applications. If you are using ADSP to send
  3362. a continuous flow of data, a larger data buffer will improve performance. If
  3363. your application is sending or receiving the user’s keystrokes, a smaller buffer
  3364. should be adequate. The constant minDSPQueueSize indicates the minimum queue
  3365. size that you can use.
  3366.  
  3367. If you are using a version of the .DSP driver prior to version 1.5, you must
  3368. allocate send and receive queues that are 12% larger than the actual buffer
  3369. sizes you need, to provide some extra space for use by the .DSP driver. Version
  3370. 1.5 and later versions of the .DSP driver use a much smaller, and variable,
  3371. portion of buffer space for overhead.
  3372.  
  3373. 3.  Use the dspInit command to establish a connection end. You must provide
  3374. pointers to the connection control block, send buffer, receive buffer, and
  3375. attention message buffer. You may also provide a pointer to the user routine
  3376. that ADSP calls when your connection end receives an unsolicited connection
  3377. event. User routines are discussed in “Writing a User Routine For Connection
  3378. Events” later in this chapter.
  3379.  
  3380. If there is a specific socket that you want to use for the connection end, you
  3381. can specify the socket number in the localSocket parameter. If you want ADSP to
  3382. assign the socket for you, specify 0 for the localSocket parameter. ADSP returns
  3383. the socket number when the dspInit command completes execution.
  3384.  
  3385. 4.  If you wish to do so, you can use the NBPRegister function to add the name
  3386. and address of your connection end to the node’s names table. The NBPRegister
  3387. function is described in the AppleTalk Manager chapter of Volume II. 
  3388.  
  3389. 5.  You can use the dspOptions command to set several parameters that control
  3390. the behavior of the connection end. Because every parameter has a default value,
  3391. the use of the dspOptions command is optional. You can specify values for the
  3392. following parameters:
  3393.  
  3394.   •   The sendBlocking parameter, which sets the maximum number of bytes that
  3395.       may accumulate in the send buffer before ADSP sends a packet to the
  3396.       remote connection end. You can experiment with different values of the
  3397.       sendBlocking parameter to determine which provides the best performance;
  3398.       the default value of 16 bytes gives good performance under most
  3399.       circumstances.
  3400.  
  3401.   •   The badSeqMax parameter, which sets the maximum number of out-of-sequence
  3402.       data packets that the local connection end can receive before requesting
  3403.       the remote connection end to retransmit the missing data. Under most
  3404.       circumstances, the default value of 3 provides good performance.
  3405.  
  3406.   •   The useCheckSum parameter, which determines whether DDP should compute a
  3407.       checksum and include it in each packet that it sends to the remote
  3408.       connection end. Using checksums slows communications slightly. Normally
  3409.       ADSP and DDP perform enough error checking to ensure safe delivery of all
  3410.       data; set the useCheckSum parameter to 1 only if you feel that the
  3411.       network is highly unreliable.
  3412.  
  3413. 6.  Call the dspOpen command to open the connection. The dspOpen command has
  3414. four possible modes of operation: ocAccept, ocEstablish, ocRequest, and
  3415. ocPassive. Normally you use either the ocRequest or ocPassive mode. You must
  3416. specify one of these four modes for the ocMode parameter when you call the
  3417. dspOpen command. 
  3418.  
  3419. The ocAccept mode is used only by connection servers. The ocEstablish mode is
  3420. used by routines that determine their connection-opening parameters and
  3421. establish a connection independently of ADSP, but use ADSP to transmit and
  3422. receive data.
  3423.  
  3424. Use the ocRequest mode when you want to establish communications with a specific
  3425. socket on the internet. When you execute the dspOpen command in the ocRequest
  3426. mode, ADSP sends an open-connection request to the address you specify. 
  3427.  
  3428. If the socket to which you send the open-connection request is a connection
  3429. listener, the connection server that operates that connection listener can
  3430. choose any socket on the internet to be the connection end that responds to the
  3431. open-connection request. To restrict the socket from which you will accept a
  3432. response to your open-connection request, specify a value for the filterAddress
  3433. parameter to the dspOpen command. When your connection end receives a response
  3434. from a socket that meets the restrictions of the filterAddress parameter, it
  3435. acknowledges the response and ADSP completes the connection. 
  3436.  
  3437. To use the ocRequest mode, you must know the complete internet address of the
  3438. remote socket, and the ADSP client at that address must either be a connection
  3439. listener or have executed the dspOpen command in the ocPassive mode. You can use
  3440. the NBPLookup function to obtain a list of names of objects on the internet and
  3441. to determine the internet address of a socket when you know its name. The
  3442. NBPLookup function is described in the AppleTalk Manager chapter of Volume II.
  3443. Enhancements to the wildcard-lookup feature of NBP are discussed in “A New NBP
  3444. Wildcard Character” earlier in this chapter. 
  3445.  
  3446. Use the ocPassive mode when you expect to receive an open-connection request
  3447. from a remote socket. You can specify a value for the filterAddress parameter to
  3448. restrict the network number, node ID, or socket number from which you will
  3449. accept an open-connection request. When your connection end receives an
  3450. open-connection request that meets the restrictions of the filterAddress
  3451. parameter, it acknowledges the request and ADSP completes the connection. 
  3452.  
  3453. You can poll the state field in the connection control block to determine when
  3454. the connection end is waiting to receive an open-connection request, when the
  3455. connection end is waiting to receive an acknowledgment of an open-connection
  3456. request, and when the connection is open. The CCB is described in “The ADSP
  3457. Connection Control Block” earlier in this chapter. Alternatively, you can check
  3458. the result code for the dspOpen command when the function completes execution.
  3459. If the function returns the noErr result code, then the connection is open.
  3460.  
  3461. 7.  Use the dspRead command to read data that your connection end has received
  3462. from the remote connection end. Use the dspWrite command to send data to the
  3463. remote connection end. Use the dspAttention command to send attention messages
  3464. to the remote connection end.
  3465.  
  3466. The dspWrite command places data in the send queue. ADSP is a full-duplex,
  3467. symmetric communication protocol. You can send data at any time, and your
  3468. connection end can receive data at any time, even at the same time as you are
  3469. sending data. ADSP transmits the data in the send queue when one of the
  3470. following conditions occurs:
  3471.  
  3472.   •   You call the dspWrite command with the flush parameter set to a nonzero
  3473.       number.
  3474.  
  3475.   •   The number of bytes in the send queue equals or exceeds the blocking
  3476.       factor that you set with the dspOptions command.
  3477.  
  3478.   •   The send timer expires. The send timer sets the maximum amount of time
  3479.       that can pass before ADSP sends all unsent data in the send queue to the
  3480.       remote connection end. ADSP calculates the best value to use for this
  3481.       timer and sets it automatically.
  3482.  
  3483.   •   A connection event requires that the local connection end send an
  3484.       acknowlegment packet to the remote connection end.
  3485.  
  3486. If you send more data to the send queue than it can hold, the dspWrite command
  3487. does not complete execution until it has written all the data to the send queue.
  3488. If you execute the dspWrite command asynchronously, ADSP returns control to your
  3489. program and writes the data to the send queue as quickly as it can. This
  3490. technique provides the most efficient use of the send queue by your program and
  3491. by ADSP. Because ADSP does not remove data from the send queue until that data
  3492. has not only been sent but also acknowledged by the remote connection end, using
  3493. the flush parameter to the dspWrite command does not guarantee that the send
  3494. queue is empty. You can use the dspStatus command to determine how much free
  3495. buffer space is available in the send queue. 
  3496.  
  3497. The dspRead command reads data from the receive queue into your application’s
  3498. private data buffer. ADSP does not transmit data until there is space available
  3499. in the other end’s receive queue to accept it. Because a full receive queue
  3500. slows the communication rate, you should read data from the receive queue as
  3501. often as necessary to keep sufficient buffer space available for new data. You
  3502. can use either of two techniques to do this:
  3503.  
  3504.   •   Allocate a small receive queue (about 600 bytes) and call the dspRead
  3505.       command asynchronously. Your completion routine for the dspRead command
  3506.       should then call the dspRead command again.
  3507.  
  3508.   •   Allocate a large receive queue and call the dspRead command less
  3509.       frequently.
  3510.  
  3511. If there is less data in the receive queue than the amount you specify with the
  3512. reqCount parameter to the dspRead command, the command does not complete
  3513. execution until there is enough data available to satisfy the request. There are
  3514. three exceptions to this rule: If the end-of-message bit in the ADSP packet
  3515. header is set, the dspRead command reads the data in the receive queue, returns
  3516. the actual amount of data read in the actCount parameter, and returns the eom
  3517. parameter set to 1. If you have closed the connection end before calling the
  3518. dspRead command (that is, the connection is half open), the command reads
  3519. whatever data is available and returns the actual amount of data read in the
  3520. actCount parameter. If ADSP has closed the connection before you call the
  3521. dspRead command , the function returns the noErr result code with the actCount
  3522. parameter set to 0 and the eom parameter set to 0.
  3523.  
  3524. In addition to the byte stream data format implemented by the dspRead and
  3525. dspWrite commands, ADSP provides a mechanism for sending and receiving control
  3526. signals or information separate from the byte stream. You use the dspAttention
  3527. command to send an attention code and an attention message to the remote
  3528. connection end. When your connection end receives an attention message, ADSP’s
  3529. interrupt handler sets the eAttention flag in the userFlags field of the
  3530. connection control block and calls your user routine. Your user routine must
  3531. clear the userFlags field, and can then read the attention code and attention
  3532. message and take whatever action you deem appropriate. 
  3533.  
  3534. Because ADSP is often used by terminal emulation programs and other applications
  3535. that pass the data they receive on to the user without processing it, attention
  3536. messages provide a mechanism for the applications that are clients of the
  3537. connection ends to communicate with each other. For example, you could use
  3538. attention messages to implement a handshaking and data checking protocol for a
  3539. program that transfers disk files between two applications, neither one of which
  3540. is a file server. Or a database server on a mainframe computer that uses ADSP to
  3541. communicate with Macintosh computer workstations could use the attention
  3542. mechanism to inform the workstations when the database is about to be closed
  3543. down for maintenance.
  3544.  
  3545. 8.  When you are ready to close the ADSP connection, you can use the dspClose or
  3546. dspRemove commands to close the connection end. Use the dspClose command if you
  3547. intend to open another connection using that connection end, and do not want to
  3548. release the memory you allocated for the connection end. Use the dspRemove
  3549. command if you are completely finished with the connection end and want to
  3550. release the memory.
  3551.  
  3552. You can continue to read data from the receive queue after you have called the
  3553. dspClose command, but not after you have called the dspRemove command. You can
  3554. use the dspStatus command to determine whether there is any data remaining in
  3555. the receive queue, or you can read data from the receive queue until both the
  3556. actCount and eom fields of the dspRead parameter block return 0.
  3557.  
  3558. If you set the abort parameter for the dspClose or dspRemove commands to 0, then
  3559. ADSP does not close the connection or the connection end until it has sent—and
  3560. received acknowledgment for—all data in the send queue and any pending attention
  3561. messages. If you set the abort parameter to 1, then ADSP discards any data in
  3562. the send queue and any attention messages that have not already been sent.
  3563.  
  3564. After you have executed the dspRemove command, you can release the memory you
  3565. allocated for the connection control block and data buffers.
  3566.  
  3567. Listing 29-2 illustrates the use of ADSP. It opens the .MPP and .DSP drivers,
  3568. and allocates memory for its internal data buffers, for the CCB, and for the
  3569. send, receive, and attention message buffers. Then it uses the dspInit command
  3570. to establish a connection end, and uses NBP to register the name of the
  3571. connection end on the internet. The routine uses the dspOptions command to set
  3572. the blocking factor to 24 bytes. Next, it uses NBP to determine the address of a
  3573. socket whose name was chosen by the user and sends an open-connection request 
  3574. (dspOpen) to that socket. When the dspOpen command completes execution, the
  3575. routine sends data and an attention message to the remote connection end, and
  3576. reads data from its receive buffer. Finally, the routine closes the connection
  3577. end with the dspRemove command and releases the memory it allocated.
  3578.  
  3579. Listing 29-2.  Using ADSP to establish and use a connection (TO BE PROVIDED)
  3580.  
  3581. _______________________________________________________________________________
  3582.  
  3583. æKY Creating…and…Using…a…Connection…Listener
  3584. æC »Creating and Using a Connection Listener                             AppleTalk Manager
  3585. _______________________________________________________________________________
  3586.  
  3587. A connection listener is a special sort of ADSP connection end that cannot
  3588. receive or transmit data streams or attention messages. The sole function of a
  3589. connection listener is to wait passively to receive an open-connection request
  3590. and to inform its client, the connection server, when it receives one. The
  3591. connection server can then accept or deny the open-connection request. If it
  3592. accepts the request, the connection server selects a socket to use as a
  3593. connection end, establishes a connection end on that socket, and sends an
  3594. acknowledgement and connection request back to the requesting connection end.
  3595. The connection server can use the same socket as it used for the connection
  3596. listener, or can select a different socket as the connection end.
  3597.  
  3598. Use the following procedure to establish a connection listener and to use that
  3599. connection listener to open a connection with a remote connection end:
  3600.  
  3601. 1.  Use the MPPOpen command to open the .MPP driver and then use the OpenDriver
  3602. command to open the .DSP driver. The OpenDriver routine returns the reference
  3603. number for the .DSP driver; you must supply this reference number each time you
  3604. call the .DSP driver.
  3605.  
  3606. 2.  Allocate nonrelocatable memory for a connection control block. A connection
  3607. listener does not need send and receive buffers or an attention message buffer.
  3608. The memory that you allocate becomes the property of ADSP when you call the
  3609. dspCLInit command to establish a connection listener. You cannot write any data
  3610. to this memory except through calls to ADSP, and you must ensure that the memory
  3611. remains locked until you call the dspRemove command to eliminate the connection
  3612. end. The connection control block is 242 bytes in size. 
  3613.  
  3614. 3.  Call the dspCLInit command to establish a connection listener. You must
  3615. provide a pointer to the connection control block.
  3616.  
  3617. If there is a specific socket that you want to use for the connection listener,
  3618. you can specify the socket number in the localSocket parameter. If you want ADSP
  3619. to assign the socket for you, specify 0 for the localSocket parameter, and ADSP
  3620. returns the socket number when the dspCLInit command completes execution.
  3621.  
  3622. 4.  If you wish, you can use the NBPRegister function to add the name and
  3623. address of your connection listener to the node’s names table. The NBPRegister
  3624. function is described in the AppleTalk Manager chapter of Volume II.
  3625.  
  3626. 5.  Use the dspCLListen command to cause the connection listener to wait for an
  3627. open-connection request. Because the dspCLListen command does not complete
  3628. execution until it receives a connection request, you should call this function
  3629. asynchronously. You can specify a value for the filterAddress parameter to
  3630. restrict the network number, node ID, or socket number from which you will
  3631. accept an open-connection request. 
  3632.  
  3633. When the dspCLListen command receives an open-connection request that meets the
  3634. restrictions of the filterAddress parameter, it returns a noErr result code (if
  3635. you executed the function asynchronously, it places a noErr result code in the
  3636. ioResult parameter) and places values in the parameter block for the remoteCID,
  3637. remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters. 
  3638.  
  3639. 6.  If you want to open the connection, use the dspInit command to establish a
  3640. connection end. You can use any available socket on the node for the connection
  3641. end, including the socket that you used for the connection listener. Because a
  3642. single socket can have more than one CCB connected with it, the socket can
  3643. function simultaneously as a connection end and a connection listener. 
  3644.  
  3645. You can check the address of the remote socket to determine if it meets your
  3646. criteria for a connection end. Although the filterAddress parameter to the
  3647. dspCLListen command provides some screening of socket addresses, it cannot check
  3648. for network number ranges, for example, or for a specific set of socket numbers.
  3649. If for some reason you want to deny the connection request, call the DSPDeny
  3650. function, specifying the connection control block of the connection listener in
  3651. the ccbRefNum parameter. Because the dspCLListen command completes execution
  3652. when it receives an open-connection request, you must return to step 5 to wait
  3653. for another connection request.
  3654.  
  3655. 7.  Call the dspOpen command, specifying ocAccept for the ocMode parameter and
  3656. specifying in the ccbRefNum parameter the reference number of the connection end
  3657. that you want to use. When you call the dspOpen command , you must provide the
  3658. values returned by the dspCLListen command for the remoteCID, remoteAddress,
  3659. sendSeq, sendWindow, and attnSendSeq parameters.
  3660.  
  3661. You can poll the state field in the connection control block to determine when
  3662. the connection is open. The CCB is described in “The ADSP Connection Control
  3663. Block” earlier in this chapter. Alternatively, you can check the result code for
  3664. the dspOpen command when the function completes execution. If the function
  3665. returns the noErr result code, then the connection is open.
  3666.  
  3667. 8.  You can now send and receive data and attention messages over the
  3668. connection, as described in the preceding section, “Opening and Maintaining an
  3669. ADSP Connection.” When you are ready to close the connection, you can use the
  3670. dspClose or dspRemove commands, which are also described in the preceding
  3671. section.
  3672.  
  3673. 9.  When you are finished using the connection listener, you can use the
  3674. dspCLRemove command to eliminate it. Once you have called the dspCLRemove
  3675. command, you can release the memory you allocated for the connection listener’s
  3676. connection control block.
  3677.  
  3678. Listing 29-3 illustrates the use of ADSP to establish and use a connection
  3679. listener. It opens the .MPP and .DSP drivers, and allocates memory for the CCB.
  3680. Then it uses the dspCLInit command to establish a connection listener, uses NBP
  3681. to register the name of the connection end on the internet, and uses the
  3682. dspCLListen command to wait for a connection request. When the routine receives
  3683. a connection request, it calls the dspOpen command to complete the connection.
  3684.  
  3685. Listing 29-3.  Using ADSP to Establish and Use a Connection Listener (TO BE
  3686. PROVIDED)
  3687.  
  3688. _______________________________________________________________________________
  3689.  
  3690. æKY Writing…a…User…Routine…For…Connection…Events
  3691. æC »Writing a User Routine For Connection Events                         AppleTalk Manager
  3692. _______________________________________________________________________________
  3693.  
  3694. When you execute the dspInit command, you can specify a pointer to a routine
  3695. that you provide (referred to as the user routine). Whenever an unsolicited
  3696. connection event occurs, ADSP sets a flag in the connection control block (CCB)
  3697. and calls the user routine. The user routine must clear the flag to acknowledge
  3698. that it has read the flag field, and can then respond to the event in any manner
  3699. you deem appropriate. The CCB flags are described in “The ADSP Connection
  3700. Control Block” earlier in this chapter. There are four types of unsolicited
  3701. connection events that set flags in the CCB, as follows:
  3702.  
  3703.   •   ADSP has been informed by the remote connection end that the remote
  3704.       connection end is about to close the connection. An appropriate reponse
  3705.       might be to store a flag indicating that the connection end is about to
  3706.       close. When your application regains control, it can then display a
  3707.       dialog box informing the user of this event and asking whether the
  3708.       application should attempt to reconnect later.
  3709.  
  3710.   •   ADSP has determined that the remote connection end is not responding, and
  3711.       so has closed the connection. Your user routine can attempt to open a new
  3712.       connection immediately. Alternatively, you can store a flag indicating
  3713.       that the connection has closed and, when your application regains
  3714.       control, it can display a dialog box asking the user whether to attempt
  3715.       to reconnect.
  3716.  
  3717.   •   ADSP has received an attention message from the remote connection end.
  3718.       Depending on what you are using the attention message mechanism for, you
  3719.       might want to read the attention code in the attnCode field of the CCB
  3720.       and the attention message pointed to by the attnPtr field of the CCB.
  3721.  
  3722.   •   ADSP has received a forward reset command from the remote client end, has
  3723.       discarded all ADSP data not yet delivered—including the data in the
  3724.       local client end’s receive queue—and has resynchronized the connection.
  3725.       Your response to this event depends on the purpose for which you are
  3726.       using the forward reset mechanism. You might want to resend the last data
  3727.       you have sent or inform the user of the event.
  3728.  
  3729. When ADSP calls your user routine, the CPU is in interrupt-processing mode and
  3730. register A1 contains a pointer to the CCB of the connection end that generated
  3731. the event. You can examine the userFlags field of the CCB to determine what
  3732. event caused the interrupt, and you can examine the state field of the CCB to
  3733. determine the current state of the connection. 
  3734.  
  3735. Because the CPU is set to interrupt-processing mode, your user routine must
  3736. preserve all registers other than A0, A1, D0, D1, and D2. Your routine must not
  3737. make any direct or indirect calls to the Memory Manager, and can’t depend on
  3738. handles to unlocked blocks being valid. If you want to use any of your
  3739. application’s global variables, you must save the contents of the A5 register
  3740. before using the variables, and you must restore the A5 register before your
  3741. routine terminates. Listing 29-4 illustrates the use of the CCB to store the
  3742. contents of the A5 register while your routine is executing.
  3743.  
  3744. If you want to execute a routine each time an unsolicited connection event
  3745. occurs but the interrupt environment is too restrictive, you can specify a NIL
  3746. pointer to the user routine and periodically poll the userFlags field of the CCB
  3747. instead.
  3748.  
  3749. To ensure that you do not lose any attention messages, you must read any
  3750. attention messages into an internal buffer before you clear the bit in the
  3751. userFlags field.
  3752.  
  3753. Listing 29-4 is an example of a user routine. When this routine is called, it
  3754. first checks the connection control block to determine the source of the
  3755. interrupt and then clears the bit in the userFlags field of the CCB. If the
  3756. routine has received an attention message, the user routine reads the message
  3757. into an internal buffer before it clears the flag bit.
  3758.  
  3759. Listing 29-4.  An ADSP user routine (TO BE PROVIDED)
  3760. _______________________________________________________________________________
  3761.  
  3762. æKY DSP…Driver…Commands
  3763. æC »DSP Driver Commands                                                  AppleTalk Manager
  3764. _______________________________________________________________________________
  3765.  
  3766. The .DSP driver implements the AppleTalk Data Stream protocol (ADSP). You send
  3767. commands to ADSP and obtain information about ADSP by executing the .DSP driver
  3768. commands described in this section.  
  3769. To use a .DSP driver command, call PBControl passing a pointer to the .DSP
  3770. parameter block as a parameter and the async parameter is a Boolean that
  3771. specifies whether the function is to execute synchronously or asynchronously.
  3772. Set the async parameter to TRUE to execute the function asynchronously.
  3773.  
  3774. The .DSP parameter block is shown in “The .DSP Parameter Block” earlier in this
  3775. chapter. The parameters used with each function are described in this section.
  3776.  
  3777. For a general discussion of the use of ADSP, see “Using ADSP” earlier in this
  3778. chapter.
  3779.  
  3780. _______________________________________________________________________________
  3781.  
  3782. æKY Establishing…and…Terminating…an…ADSP…Connection
  3783. æC »Establishing and Terminating an ADSP Connection                      AppleTalk Manager
  3784. _______________________________________________________________________________
  3785.  
  3786. You can use the functions described in this section to 
  3787.  
  3788.   •   establish a connection end
  3789.   •   open a connection
  3790.   •   assign an identification number to a connection end
  3791.   •   set the values for parameters that control the behavior of a connection
  3792.       end
  3793.   •   close a connection end
  3794.   •   eliminate a connection end
  3795.  
  3796. The parameter block for the dspInit command looks like this:
  3797.  
  3798. Parameter block
  3799.   ¨  16  ioResult  word  result code 
  3800.   Æ  26  csCode  word  always dspInit
  3801.   ¨  32  ccbRefNum  word  reference number for CCB
  3802.   Æ  34  ccbPtr  long  pointer to connection control block
  3803.   Æ  38  userRoutine  long  pointer to routine to call on 
  3804.           connection events
  3805.   Æ  42  sendQSize  word  size in bytes of the send queue
  3806.   Æ  44  sendQueue  long  pointer to send queue
  3807.   Æ  48  recvQSize  word  size in bytes of the receive queue
  3808.   Æ  50  recvQueue  long  pointer to receive queue
  3809.   Æ  54  attnPtr  long  pointer to buffer for incoming 
  3810.           attention messages
  3811.   ´  58  localSocket  byte  DDP socket number for this 
  3812.           connection end
  3813.  
  3814. The dspInit command establishes a connection end; that is, it assigns a specific
  3815. socket for use by ADSP and initializes the variables that ADSP uses to maintain
  3816. the connection. The dspInit command does not open the connection end or
  3817. establish a connection with a remote connection end; follow the dspInit command
  3818. with the dspOpen command to perform those tasks. Use the dspCLInit command to
  3819. establish a connection listener. Use the dspRemove command to eliminate a
  3820. connection end.
  3821.  
  3822. When you send bytes to a remote connection end, ADSP stores the bytes in a
  3823. buffer called the send queue. It keeps the bytes you sent in the send queue
  3824. until the remote connection end acknowledges their receipt, so that they are
  3825. available to be retransmitted if necessary. When the local connection end
  3826. receives bytes, it stores them in a buffer called the receive queue until you
  3827. read them. 
  3828.  
  3829. You must allocate memory for the send and receive queues, and for a buffer that
  3830. holds incoming attention messages. You must also allocate a nonrelocatable block
  3831. of memory for the connection control block for this connection end. 
  3832.  
  3833. Note:  When you use the dspInit command, the memory that you allocate becomes
  3834. the property of ADSP. You cannot write any data to this memory except by calling
  3835. ADSP routines, and you must ensure that the memory remains locked until you call
  3836. the dspRemove command to eliminate the connection end. 
  3837.  
  3838. Parameters
  3839.  
  3840. ioResult
  3841. The result of the function. When you execute the function asynchronously, the
  3842. function sets this parameter to 1 and returns a function result of noErr as soon
  3843. as the function begins execution. When the function completes execution, it sets
  3844. the ioResult parameter to the actual result code. 
  3845.  
  3846. csCode
  3847. The routine selector, you should set this to dspInit for this command.
  3848.  
  3849. ccbRefNum
  3850. The reference number for the connection control block. The dspInit command
  3851. returns this number. You must provide this number in all subsequent calls to
  3852. this connection end.
  3853.  
  3854. ccbPtr
  3855. A pointer to the connection control block that you allocated. The connection
  3856. control block is 242 bytes in size, and is described in “The ADSP Connection
  3857. Control Block” earlier in this chapter.
  3858.  
  3859. userRoutine
  3860. A pointer to a routine that is to be called each time the connection end
  3861. receives an unsolicited connection event. Specify NIL for this parameter if you
  3862. do not want to supply a user routine. Connection events and user routines are
  3863. discussed in “Writing a User Routine For Connection Events” earlier in this
  3864. chapter.
  3865.  
  3866. sendQSize
  3867. The size in bytes of the send queue. A queue size of 600 bytes should work well
  3868. for most applications. If you are using ADSP to send a continuous flow of data,
  3869. a larger data buffer will improve performance. If your application is sending
  3870. the user’s keystrokes, a smaller buffer should be adequate. The constant
  3871. minDSPQueueSize indicates the minimum queue size that you can use.
  3872.  
  3873.  
  3874. sendQueue
  3875. A pointer to the send queue that you allocated. 
  3876.  
  3877. recvQSize
  3878. The size in bytes of the receive queue. A queue size of 600 bytes should work
  3879. well for most applications. If you are using ADSP to receive a continuous flow
  3880. of data, a larger data buffer will improve performance. If your application is
  3881. receiving a user’s keystrokes, a smaller buffer should be adequate. The constant
  3882. minDSPQueueSize indicates the minimum queue size that you can use.
  3883.  
  3884. recvQueue
  3885. A pointer to the receive queue that you allocated.
  3886.  
  3887. attnPtr
  3888. A pointer to the attention-message buffer that you allocated. The
  3889. attention-message buffer must be the size of the constant attnBufSize.
  3890.  
  3891. localSocket
  3892. The DDP socket number of the socket that you want ADSP to use for this
  3893. connection end. Specify 0 for this parameter to cause ADSP to assign the socket.
  3894. In the latter case, ADSP returns the socket number when the dspInit command
  3895. completes execution.
  3896.  
  3897. Result codes
  3898. noErr                0  no error
  3899. ddpSktErr          –91  error opening socket
  3900. errDSPQueueSize  –1274  send or receive queue too small
  3901.  
  3902. The parameter block for the dspOptions command looks like this:
  3903.  
  3904. Parameter block
  3905.   ¨  16  ioResult  word  result code 
  3906.   Æ  26  csCode  word  always dspOptions
  3907.   Æ  32  ccbRefNum  word  reference number of connection end
  3908.   Æ  34  sendBlocking  word  send-blocking threshold
  3909.   Æ  38  badSeqMax  byte  threshold to send retransmit advice
  3910.   Æ  39  useCheckSum  byte  use DDP checksum?
  3911.  
  3912. The dspOptions command allows you to set values for several parameters that
  3913. affect the behavior of the local connection end. You can set the options for any
  3914. established connection end, whether open or not.
  3915.  
  3916. Parameters
  3917.  
  3918. ioResult
  3919. The result of the function. When you execute the function asynchronously, the
  3920. function sets this parameter to 1 and returns a function result of noErr as soon
  3921. as the function begins execution. When the function completes execution, it sets
  3922. the ioResult parameter to the actual result code. 
  3923.  
  3924. csCode
  3925. The routine selector, you should set this to dspOptions for this command.
  3926.  
  3927. ccbRefNum
  3928. The connection control block reference number that was returned by the dspInit
  3929. command.
  3930.  
  3931. sendBlocking
  3932. The maximum number of bytes that may accumulate in the send buffer before ADSP
  3933. sends a packet to the remote connection end. ADSP sends a packet before the
  3934. maximum number of bytes accumulates if the period specified by the send timer
  3935. expires, if you execute the dspWrite command with the flush parameter set to 1,
  3936. or if a connection event requires that the local connection end send an
  3937. acknowledgement packet to the remote connection end.
  3938.  
  3939. You can set the sendBlocking parameter to any value from 1 byte to the maximum
  3940. size of a packet (572 bytes). If you set the sendBlocking parameter to 0, the
  3941. current value for this parameter is not changed. The default value for the
  3942. sendBlocking parameter is 16 bytes.
  3943.  
  3944. badSeqMax
  3945. The maximum number of out-of-sequence data packets that the local connection end
  3946. can receive before requesting the remote connection end to retransmit the
  3947. missing data. Because a connection end does not acknowledge the receipt of a
  3948. data packet received out of sequence, the remote connection end’s retransmit
  3949. timer will expire eventually and it will retransmit the data. The badSeqMax
  3950. allows you to cause the data to be retransmitted before the remote connection
  3951. end’s retransmit timer has expired.
  3952.  
  3953. You can set the badSeqMax parameter to any value from 1 to 255. If you set the
  3954. badSeqMax parameter to 0, the current value for this parameter is not changed.
  3955. The default value for the badSeqMax parameter is 3.
  3956.  
  3957. useCheckSum
  3958. A flag specifying whether DDP should compute a checksum and include it in each
  3959. packet that it sends to the remote connection end. Set this parameter to 1 to
  3960. cause DDP to use checksums, or to 0 if you do not want DDP to use checksums. The
  3961. default value for useCheckSum is 0.
  3962.  
  3963. ADSP cannot include a checksum in a packet that has a short DDP header; that is,
  3964. a packet being sent over LocalTalk to a remote socket that is on the same cable
  3965. as the local socket. Note that the useCheckSum parameter affects only whether
  3966. ADSP includes a checksum in a packet that it is sending. If ADSP receives a
  3967. packet that includes a checksum, it validates the checksum regardless of the
  3968. setting of the useCheckSum parameter. 
  3969.  
  3970. Result codes
  3971. noErr          0  no error
  3972. errRefNum  –1280  bad connection reference number
  3973.  
  3974. The parameter block for the dspOpen command looks like this:
  3975.  
  3976. Parameter block
  3977.   ¨  16  ioResult  word  result code 
  3978.   Æ  26  csCode  word  always dspOpen
  3979.   Æ  32  ccbRefNum  word  reference number of connection end
  3980.   ¨  34  localCID  word  ID of this connection end
  3981.   ´  36  remoteCID  word  ID of remote connection end
  3982.   ´  38  remoteAddress  long  remote internet address
  3983.   Æ  42  filterAddress  long  filter for open connection requests
  3984.   ´  46  sendSeq  long  initial send sequence number
  3985.   ´  50  sendWindow  word  initial size of remote receive buffer
  3986.   Æ  52  recvSeq  long  initial receive sequence number
  3987.   ´  56  attnSendSeq  long  attention send sequence number
  3988.   Æ  60  attnRecvSeq  long  attention receive sequence number
  3989.   Æ  64  ocMode  byte  connection opening mode
  3990.   Æ  65  ocInterval  byte  interval between open requests
  3991.   Æ  66  ocMaximum  byte  retries of open connection request
  3992.  
  3993. You use the ocMode field of the parameter block to specify the opening mode that
  3994. the dspOpen command is to use. The dspOpen command puts a connection end into
  3995. one of four possible opening modes, as follows: 
  3996.  
  3997.   •   The ocRequest mode, in which ADSP attempts to open a connection with the
  3998.       socket at the internet address you specify with the remoteAddress
  3999.       parameter. If the socket you specify as a remote address is a connection
  4000.       listener, it is possible that your application will receive a connection
  4001.       acknowledgement and request from a different address than the one to
  4002.       which you sent the open-connection request. You can use the filterAddress
  4003.       parameter to restrict the addresses with which you will accept a
  4004.       connection.
  4005.  
  4006. The dspOpen command completes execution in the ocRequest mode when either ADSP
  4007. establishes a connection, your connection end receives a connection denial from
  4008. the remote connection end, your connection end denies the connection request
  4009. returned by a connection listener, or ADSP cannot complete the connection (ADSP
  4010. has exceeded the maximum number of retries that you specified with the ocMaximum
  4011. parameter).
  4012.  
  4013.   •   The ocPassive mode, in which the connection end waits to receive an
  4014.       open-connection request from a remote connection end. You can use the
  4015.       filterAddress parameter to restrict the addresses from which you will
  4016.       accept a connection request.
  4017.  
  4018. The dspOpen command completes execution in the ocPassive mode when ADSP
  4019. establishes a connection or when either connection end receives a connection
  4020. denial.
  4021.  
  4022.   •   The ocAccept mode, used by connection servers to complete an
  4023.       open-connection dialog. When a connection server is informed by its
  4024.       connection listener that the connection listener has received an
  4025.       open-connection request, the connection server uses the dspInit command
  4026.       to establish a connection end and then calls the dspOpen command in
  4027.       ocAccept mode to complete the connection. You must obtain the following
  4028.       parameters from the dspCLListen command and provide them to the dspOpen
  4029.       command: remoteAddress, remoteCID, sendSeq, sendWindow, and attnSendSeq.
  4030.       Connection listeners and connection servers are described in “Creating
  4031.       and Using a Connection Listener,” earlier in this chapter, and in
  4032.       “Establishing and Terminating an ADSP Connection Listener,” later in this
  4033.       chapter.
  4034.  
  4035. The dspOpen command completes execution in the ocAccept mode when ADSP
  4036. establishes a connection or when either connection end receives a connection
  4037. denial.
  4038.  
  4039.   •   The ocEstablish mode, in which ADSP considers the connection end
  4040.       established and the connection state open. This mode is for use by
  4041.       clients that determine their connection-opening parameters without using
  4042.       ADSP or the .DSP driver to do so.
  4043.  
  4044. You must first use the dspInit command to establish a connection end and then
  4045. execute the dspNewCID command to obtain an identification number for the local
  4046. connection end. You must then communicate with the remote connection end to send
  4047. it the local connection ID and to determine the values of the following
  4048. parameters: remoteAddress, remoteCID, sendSeq, sendWindow, recvSeq, attnSendSeq,
  4049. and attnRecvSeq. Only then can you execute the dspOpen command in the
  4050. ocEstablish mode.
  4051.  
  4052. The dspOpen command completes execution in the ocEstablish mode immediately. 
  4053. The use of parameters by the dspOpen command depends on the mode in which the
  4054. function is executed, as follows:
  4055.  
  4056. ocRequest         ocPassive         ocAccept          ocEstablish
  4057.  
  4058. ¨ ioResult        ¨ ioResult        ¨ ioResult        ¨ ioResult
  4059. Æ csCode          Æ csCode          Æ csCode          Æ csCode
  4060. Æ ccbRefNum       Æ ccbRefNum       Æ ccbRefNum       Æ ccbRefNum
  4061. ¨ localCID        ¨ localCID        ¨ localCID        — localCID
  4062. ¨ remoteCID       ¨ remoteCID       Æ remoteCID       Æ remoteCID
  4063. Æ remoteAddress   ¨ remoteAddress   Æ remoteAddress   Æ remoteAddress
  4064. Æ filterAddress   Æ filterAddress   — filterAddress   — filterAddress
  4065. ¨ sendSeq         ¨ sendSeq         Æ sendSeq         Æ sendSeq
  4066. ¨ sendWindow      ¨ sendWindow      Æ sendWindow      Æ sendWindow
  4067. — recvSeq         — recvSeq         — recvSeq         Æ recvSeq
  4068. ¨ attnSendSeq     ¨ attnSendSeq     Æ attnSendSeq     Æ attnSendSeq
  4069. — attnRecvSeq     — attnRecvSeq     — attnRecvSeq     Æ attnRecvSeq
  4070. Æ ocMode          Æ ocMode          Æ ocMode          Æ ocMode
  4071. Æ ocInterval      Æ ocInterval      Æ ocInterval      — ocInterval
  4072. Æ ocMaximum       Æ ocMaximum       Æ ocMaximum       — ocMaximum
  4073.  
  4074. Parameters
  4075.  
  4076. ioResult
  4077. The result of the function. When you execute the function asynchronously, the
  4078. function sets this parameter to 1 and returns a function result of noErr as soon
  4079. as the function begins execution. When the function completes execution, it sets
  4080. the ioResult parameter to the actual result code. 
  4081. csCode  The routine selector, you should set this to dspOpen for this command.
  4082.  
  4083. ccbRefNum
  4084. The connection control block reference number that was returned by the dspInit
  4085. command for the connection end that you want to use.
  4086.  
  4087. localCID
  4088. The identification number of the local connection end. This number is assigned
  4089. by ADSP when the connection is opened. ADSP includes this number in every packet
  4090. sent to a remote connection end. Before you call the dspOpen command in
  4091. ocEstablish mode, you must call the dspNewCID command to cause ADSP to assign
  4092. this value.
  4093.  
  4094. remoteCID
  4095. The identification number of the remote connection end. This parameter is
  4096. returned by the dspOpen command in the ocRequest and ocPassive modes. A
  4097. connection server must provide this number to the dspOpen command when the
  4098. server executes the function in ocAccept mode; in this case, the connection
  4099. server obtains the remoteCID value from the dspCLListen command. You must
  4100. provide the remoteCID value to the dspOpen command when you use the function in
  4101. ocEstablish mode. 
  4102.  
  4103. remoteAddress
  4104. The internet address of the remote socket with which you wish to establish
  4105. communications, consisting of a 2-byte network number, a 1-byte node ID, and a
  4106. 1-byte socket number. You must provide this parameter when you call the dspOpen
  4107. command in the ocRequest or ocEstablish modes. This parameter is returned by the
  4108. dspOpen command when you call the function in the ocPassive mode. When you call
  4109. the dspOpen command in the ocAccept mode, you must use the value for the
  4110. remoteAddress parameter that was returned by the dspCLListen command. 
  4111. filterAddress  The internet address of the socket from which you will accept a
  4112. connection request. The address consists of three fields, a 2-byte network
  4113. number, a 1-byte node ID, and a 1-byte socket number. Specify 0 for any of these
  4114. fields for which you wish to impose no restrictions. If you specify a filter
  4115. address of $00082500, for example, the connection end will accept a connection
  4116. request from any socket at node $25 of network $0008. Set the filterAddress
  4117. parameter equal to the remoteAddress parameter to accept a connection only with
  4118. the socket to which you sent a connection request.
  4119.  
  4120. When you execute the dspOpen command in the ocPassive mode, you can receive a
  4121. connection request from any ADSP connection end on the internet. When you
  4122. execute the dspOpen command in the ocRequest mode, your connection end can
  4123. receive a connection request acknowledgment from an address different from the
  4124. one you specified in the remoteAddress parameter only if the remote address you
  4125. specified was that of a connection listener. in either case, you can use the
  4126. filterAddress parameter to avoid acknowledging unwanted connection requests. 
  4127.  
  4128. When you execute the dspOpen command in the ocAccept mode, your connection
  4129. listener has already received and decided to accept the connection request. You
  4130. can specify a filter address for a connection listener with the dspCLListen
  4131. command. A connection server can use the dspCLDeny command to deny a connection
  4132. request that was accepted by its connection listener.
  4133.  
  4134. You cannot use the filter address when you execute the dspOpen command in
  4135. ocEstablish mode.
  4136.  
  4137. sendSeq
  4138. The sequence number of the first byte that the local connection end will send to
  4139. the remote connection end. ADSP uses this number to coordinate communications
  4140. and for error checking. ADSP returns a value for the sendSeq parameter when you
  4141. execute the dspOpen command in the ocRequest or ocPassive modes. When you
  4142. execute the dspOpen command in the ocAccept mode, you must specify the value for
  4143. the sendSeq parameter that was returned by the dspCLListen command. You must
  4144. provide the value for this parameter when you execute the dspOpen command in the
  4145. ocEstablish mode.
  4146.  
  4147. sendWindow
  4148. The sequence number of the last byte that the remote connection end has buffer
  4149. space to receive. ADSP uses this number to coordinate communications and for
  4150. error checking. ADSP returns a value for the sendWindow parameter when you
  4151. execute the dspOpen command in the ocRequest or ocPassive modes. When you
  4152. execute the dspOpen command in the ocAccept mode, you must specify the value for
  4153. the sendWindow parameter that was returned by the dspCLListen command. You must
  4154. provide the value for this parameter when you execute the dspOpen command in the
  4155. ocEstablish mode.
  4156.  
  4157. recvSeq
  4158. The sequence number of the next byte that the local connection end expects to
  4159. receive. ADSP uses this number to coordinate communications and for error
  4160. checking. You must provide the value for this parameter when you execute the
  4161. dspOpen command in the ocEstablish mode. The dspOpen command does not use this
  4162. parameter when you execute it in any other mode.
  4163.  
  4164. attnSendSeq
  4165. The sequence number of the next attention packet that the local connection end
  4166. will transmit. ADSP uses this number to coordinate communications and for error
  4167. checking. ADSP returns a value for the attnSendSeq parameter when you execute
  4168. the dspOpen command in the ocRequest or ocPassive modes. When you execute the
  4169. dspOpen command in the ocAccept mode, you must specify the value for the
  4170. attnSendSeq parameter that was returned by the dspCLListen command. You must
  4171. provide the value for this parameter when you execute the dspOpen command in the
  4172. ocEstablish mode.
  4173.  
  4174. attnRecvSeq
  4175. The sequence number of the next attention packet that the local connection end
  4176. expects to receive. ADSP uses this number to coordinate communications and for
  4177. error checking. You must provide the value for this parameter when you execute
  4178. the dspOpen command in the ocEstablish mode. The dspOpen command does not use
  4179. this parameter when you execute it in any other mode.
  4180.  
  4181. ocMode
  4182. The mode in which the dspOpen command is to operate, as follows: 
  4183.  
  4184. Mode         Value  Meaning
  4185. ocRequest    1      ADSP attempts to open a connection with the socket you
  4186. specify
  4187. ocPassive    2      The connection end waits to receive a connection request
  4188. ocAccept     3      The connection server accepts and acknowledges receipt of a
  4189. connection request
  4190. ocEstablish  4   ADSP considers the connection established and open; you are
  4191. responsible for setting up and synchronizing both connection ends
  4192.  
  4193. ocInterval
  4194. The period between transmissions of open-connection requests. If the remote
  4195. connection end does not acknowledge or deny an open-connection request, ADSP
  4196. retransmits the request after a time period specified by this parameter. The
  4197. time period used by ADSP is (ocInterval ¥ 10) ticks; or (ocInterval /
  4198. 6) seconds. For example, if you set the ocInterval parameter to 3, the time
  4199. period between retransmissions is 30 ticks (1/2 second). You can set the
  4200. ocInterval parameter to any value from 1 (1/6 second) to 180 (30 seconds). If
  4201. you specify 0 for the ocInterval parameter, ADSP uses the default value of 6 (1
  4202.  
  4203.  
  4204. You must provide a value for the ocInterval parameter when you execute the
  4205. dspOpen command in the ocRequest, ocPassive, or ocAccept modes. The dspOpen
  4206. command does not use this parameter when you execute it in the ocEstablish mode.
  4207.  
  4208. ocMaximum
  4209. The maximum number of times to retransmit an open-connection request before ADSP
  4210. terminates execution of the dspOpen command. If you specify 0 for the ocMaximum
  4211. parameter, ADSP uses the default value of 3. If you specify 255 for the
  4212. ocMaximum parameter, ADSP retransmits the open-connection request indefinitely
  4213. until the remote connection end either acknowledges or denies the request.
  4214.  
  4215. You must provide a value for the ocMaximum parameter when you execute the
  4216. dspOpen command in the ocRequest, ocPassive, or ocAccept modes. The dspOpen
  4217. command does not use this parameter when you execute it in the ocEstablish mode.
  4218.  
  4219. Result codes
  4220. noErr           0  no error
  4221. errOpening  –1277  attempt to open connection failed
  4222. errState    –1278  connection end must be closed
  4223. errAborted  –1279  request aborted by dspRemove or dspClose command
  4224. errRefNum   –1280  bad connection reference number
  4225.  
  4226. The parameter block for the dspNewCID command looks like this:
  4227.  
  4228. Parameter block
  4229.   ¨  16  ioResult  word  result code 
  4230.   Æ  26  csCode  word  always dspNewCID
  4231.   Æ  32  ccbRefNum  word  reference number of connection end
  4232.   ¨  34  newCID  word  ID of new connection
  4233.  
  4234. The dspNewCID command causes ADSP to assign an identification number to a
  4235. connection end without opening the connection end or attempting to establish a
  4236. connection with a remote connection end. Use this function only if you implement
  4237. your own protocol to establish communications with a remote connection end. You
  4238. must first use the dspInit command to establish a connection end. Next, you must
  4239. call the dspNewCID command to obtain a connection-end ID. Then you must
  4240. establish communication with a remote connection end and pass the ID to the
  4241. remote connection end. Finally, you must call the dspOpen command in ocEstablish
  4242. mode to cause ADSP to open the connection. See the description of the dspOpen
  4243. command for more information on establishing a connection in this fashion.
  4244.  
  4245. The ioResult parameter returns the result of the function; in the case that you
  4246. call the function asynchronously, the function sets this field to 1 as soon as
  4247. it begins execution, and changes the field to the actual result code when it
  4248. completes execution. The csCode parameter is the routine selector; you should
  4249. set this to dspNewCID for this command. The ccBRefNum parameter is the
  4250. connection control block reference number that was returned by the dspInit
  4251. command. The newCID parameter is the connection-end identification number
  4252. returned by this function. You must provide this number to the client of the
  4253. remote connection end so that it can use it for the remoteCID parameter when it
  4254. calls the dspOpen command.
  4255.  
  4256. Result codes
  4257. noErr          0  no error
  4258. errState   –1278  connection is not closed
  4259. errRefNum  –1280  bad connection reference number
  4260.  
  4261. The parameter block for the dspClose command looks like this:
  4262.  
  4263. Parameter block
  4264.   ¨  16  ioResult  word  result code 
  4265.   Æ  26  csCode  word  always dspClose
  4266.   Æ  32  ccbRefNum  word  reference number of connection end
  4267.   Æ  34  abort  byte  abort send requests if not 0
  4268.  
  4269. The dspClose command closes the connection end. The connection end is still
  4270. established; that is, ADSP retains ownership of the connection control block,
  4271. send queue, receive queue, and attention-message buffer. You can continue to
  4272. read bytes from the receive queue after you have called the dspClose command.
  4273. Use the dspRemove command instead of the dspClose command if you are through
  4274. reading bytes from the receive queue and want to release the memory associated
  4275. with the connection end. The dspClose command does not return an error if you
  4276. call it for a connection end that is already closed.
  4277.  
  4278. The ioResult parameter returns the result of the function; in the case that you
  4279. call the function asynchronously, the function sets this field to 1 as soon as
  4280. it begins execution, and changes the field to the actual result code when it
  4281. completes execution. The csCode parameter is the routine selector; you should
  4282. set this to dspClose for this command. The ccBRefNum parameter is the connection
  4283. control block reference number that was returned by the dspInit command. If the
  4284. abort parameter is nonzero, ADSP cancels any outstanding requests to send data
  4285. packets (such as the dspAttention command) and discards all data in the send
  4286. queue. If the abort parameter is 0, ADSP does not close the connection end until
  4287. all of the data in the send queue and all outstanding attention messages have
  4288. been sent and acknowledged.
  4289.  
  4290. Result codes
  4291. noErr          0  no error
  4292. errRefNum  –1280  bad connection reference number
  4293.  
  4294. The parameter block for the dspRemove command looks like this:
  4295.  
  4296. Parameter block
  4297.   ¨  16  ioResult  word  result code 
  4298.   Æ  26  csCode  word  always dspRemove
  4299.   Æ  32  ccbRefNum  word  reference number of connection end
  4300.   Æ  34  abort  byte  abort connection if not 0
  4301.  
  4302. The dspRemove command closes any open connection and eliminates the connection
  4303. end; that is, ADSP no longer retains control of the connection control block,
  4304. send queue, receive queue, and attention-message buffer. You cannot continue to
  4305. read bytes from the receive queue after you have called the dspRemove command.
  4306. After you call the dspRemove command, you can release all of the memory you
  4307. allocated for the connection end if you do not intend to reopen the connection
  4308. end.
  4309.  
  4310. The ioResult parameter returns the result of the function; in the case that you
  4311. call the function asynchronously, the function sets this field to 1 as soon as
  4312. it begins execution, and changes the field to the actual result code when it
  4313. completes execution. The csCode parameter is the routine selector; you should
  4314. set this to dspRemove for this command. The ccbRefNum parameter is the
  4315. connection control block reference number that was returned by the dspInit
  4316. command. If the abort parameter is nonzero, ADSP cancels any outstanding
  4317. requests to send data packets (such as the dspAttention command) and discards
  4318. all data in the send queue. If the abort parameter is 0, ADSP does not close the
  4319. connection end until all of the data in the send queue has been sent and
  4320. acknowledged.
  4321.  
  4322. Result codes
  4323. noErr          0  no error
  4324. errRefNum  –1280  bad connection reference number
  4325. _______________________________________________________________________________
  4326.  
  4327. æKY Establishing…and…Terminating…an…ADSP…Connection…Listener
  4328. æC »Establishing and Terminating an ADSP Connection Listener             AppleTalk Manager
  4329. _______________________________________________________________________________
  4330.  
  4331. A connection listener is a special kind of connection end that listens for
  4332. open-connection requests from remote connection ends. Connection listeners are
  4333. used by connection servers; that is, programs that assign a socket for the local
  4334. connection end only after they receive a connection request from a remote
  4335. connection end. A single connection listener, then, can receive connection
  4336. requests from any number of remote connection ends. 
  4337.  
  4338. You can use the functions in this section to
  4339.  
  4340.   •   establish a connection listener
  4341.   •   cause the connection listener to wait for a connection request
  4342.   •   deny a connection request
  4343.   •   close and eliminate a connection listener
  4344.  
  4345. The parameter block for the dspCLInit command looks like this:
  4346.  
  4347. Parameter block
  4348.   ¨  16  ioResult  word  result code 
  4349.   Æ  26  csCode  word  always dspCLInit
  4350.   ¨  32  ccbRefNum  word  reference number of connection end
  4351.   Æ  34  ccbPtr  long  pointer to CCB
  4352.   ´  58  localSocket  byte  local DDP socket number
  4353.  
  4354. The dspCLInit command establishes a connection listener; that is, it assigns a
  4355. specific socket for use by ADSP and initializes the variables that ADSP uses to
  4356. maintain a connection listener. The dspCLInit command does not cause the
  4357. connection listener to listen for connection requests; follow the dspCLInit
  4358. command with the dspCLListen command to activate the connection listener. Use
  4359. the dspInit command to establish a connection end that is not a connection
  4360. listener. Use the dspCLRemove command to eliminate a connection listener.
  4361.  
  4362. The ioResult parameter returns the result of the function; in the case that you
  4363. call the function asynchronously, the function sets this field to 1 as soon as
  4364. it begins execution, and changes the field to the actual result code when it
  4365. completes execution. The csCode parameter is the routine selector; you should
  4366. set this to dspCLInit for this command.The dspCLInit command returns the
  4367. ccbRefNum parameter, which is the reference number for the connection control
  4368. block. You must provide this number in all subsequent dspCLListen and
  4369. dspCLRemove calls to this connection listener. 
  4370. You must allocate memory for a connection control block before you call the
  4371. dspCLInit command. The ccbPtr parameter is a pointer to the connection control
  4372. block that you allocated. The connection control block is 242 bytes, and is
  4373. described in “The ADSP Connection Control Block” earlier in this chapter.
  4374.  
  4375. The localSocket parameter is the DDP socket number of the socket that you want
  4376. ADSP to use for this connection end. Specify 0 for this parameter to cause ADSP
  4377. to assign the socket. In the latter case, ADSP returns the socket number when
  4378. the dspCLInit command completes execution.
  4379.  
  4380. Result codes
  4381. noErr        0  no error
  4382. ddpSktErr  –91  error opening socket
  4383.  
  4384. The parameter block for the dspCLListen command looks like this:
  4385.  
  4386. Parameter block
  4387.   ¨  16  ioResult  word  result code 
  4388.   Æ  26  csCode  word  always dspCLListen
  4389.   Æ  32  ccbRefNum  word  reference number of connection end
  4390.   ¨  36  remoteCID  word  ID of remote connection end
  4391.   ¨  38  remoteAddress  long  remote internet address
  4392.   Æ  42  filterAddress  long  filter for open connection requests
  4393.   ¨  46  sendSeq  long  initial send sequence number
  4394.   ¨  50  sendWindow  word  initial size of remote receive buffer
  4395.   ¨  56  attnSendSeq  long  attention send sequence number
  4396.  
  4397. The dspCLListen command causes a connection listener to listen for connection
  4398. requests. You must have already used the dspCLInit command to establish a
  4399. connection listener before using the dspCLListen command. The dspCLListen
  4400. command is used only by connection servers.
  4401.  
  4402. When ADSP receives an open-connection request from a socket that satisfies the
  4403. address requirements of the filterAddress parameter, it returns values for the
  4404. remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters and
  4405. completes execution of the dspCLListen command. You must then either accept the
  4406. open-connection request by calling the dspOpen command in the ocAccept mode or
  4407. deny the request by calling the dspCLDeny command.
  4408.  
  4409. You can call the dspCLListen command several times, specifying the same
  4410. connection listener. For example, if you wanted to accept connections from any
  4411. or all of three different addresses, you could call the dspCLListen command
  4412. three times with a different value for the filterAddress parameter each time.
  4413. Note that you must execute the dspCLListen command asynchronously to take
  4414. advantage of this feature.
  4415.  
  4416. Parameters
  4417.  
  4418. ioResult
  4419. The result of the function. When you execute the function asynchronously, the
  4420. function sets this parameter to 1 and returns a function result of noErr as soon
  4421. as the function begins execution. When the function completes execution, it sets
  4422. the ioResult parameter to the actual result code.
  4423.  
  4424. csCode
  4425. The routine selector; you should set this to dspCLListen for this command.
  4426.  
  4427. ccbRefNum
  4428. The connection control block reference number that was returned by the dspCLInit
  4429. command.
  4430.  
  4431. remoteCID
  4432. The identification number of the remote connection end. You must pass this value
  4433. to the dspOpen command when you open the connection or to the dspCLDeny command
  4434. when you deny the connection request.
  4435.  
  4436. remoteAddress
  4437. The internet address of the remote socket that sent a request to open a
  4438. connection. This address consists of a 2-byte network number, a 1-byte node ID,
  4439. and a 1-byte socket number. You must pass this value to the dspOpen command when
  4440. you open the connection or to the dspCLDeny command when you deny the connection
  4441. request.
  4442.  
  4443. filterAddress
  4444. The internet address of the socket from which you will accept a connection
  4445. request. The address consists of three fields, a 2-byte network number, a 1-byte
  4446. node ID, and a 1-byte socket number. Specify 0 for any of these fields for which
  4447. you wish to impose no restrictions. If you specify a filter address of
  4448. $00082500, for example, the connection listener will accept a connection request
  4449. from any socket at node $25 of network $0008. 
  4450.  
  4451. sendSeq
  4452. The sequence number of the first byte that the local connection end will send to
  4453. the remote connection end. ADSP uses this number to coordinate communications
  4454. and for error checking. You must pass this value to the dspOpen command when you
  4455. open the connection.
  4456.  
  4457. sendWindow
  4458. The sequence number of the last byte that the remote connection end has buffer
  4459. space to receive. ADSP uses this number to coordinate communications and for
  4460. error checking. You must pass this value to the dspOpen command when you open
  4461. the connection.
  4462.  
  4463. attnSendSeq
  4464. The sequence number of the next attention packet that the local connection end
  4465. will transmit. ADSP uses this number to coordinate communications and for error
  4466. checking. You must pass this value to the dspOpen command when you open the
  4467. connection.
  4468.  
  4469. Result codes
  4470. noErr           0  no error
  4471. errState    –1278  not a connection listener
  4472. errAborted  –1279  request aborted by the dspRemove command
  4473. errRefNum   –1280  bad connection reference number
  4474.  
  4475. The parameter block for the dspCLDeny command looks like this:
  4476.  
  4477. Parameter block
  4478.   ¨  16  ioResult  word  result code 
  4479.   Æ  26  csCode  word  always dspCLDeny
  4480.   Æ  32  ccbRefNum  word  reference number of connection 
  4481.           listener
  4482.   Æ  36  remoteCID  word  ID of remote connection end
  4483.   Æ  38  remoteAddress  long  remote internet address
  4484.  
  4485. The dspCLDeny command is used by a connection server to inform a remote
  4486. connection end that its request to open a connection cannot be honored.
  4487.  
  4488. The ioResult parameter returns the result of the function; in the case that you
  4489. call the function asynchronously, the function sets this field to 1 as soon as
  4490. it begins execution, and changes the field to the actual result code when it
  4491. completes execution. The csCode parameter is the routine selector; you should
  4492. set this to dspCLDeny for this command. The ccbRefNum parameter is the reference
  4493. number for the connection listener that received the connection request. This
  4494. number is returned by the dspCLInit command when you establish a connection
  4495. listener. The remoteCID and remoteAddress parameters specify the address and ID
  4496. of the remote connection end. These parameters are returned by the dspCLListen
  4497. command.
  4498.  
  4499. Result codes
  4500. noErr           0  no error
  4501. errState    –1278  not a connection listener
  4502. errAborted  –1279  request aborted by the dspRemove command
  4503. errRefNum   –1280  bad connection reference number
  4504.  
  4505. The parameter block for the dspCLRemove command looks like this:
  4506.  
  4507. Parameter block
  4508.   ¨  16  ioResult  word  result code 
  4509.   Æ  26  csCode  word  always dspCLRemove
  4510.   Æ  32  ccbRefNum  word  reference number of connection 
  4511.           listener
  4512.   Æ  34  abort  byte  abort connection listener if not 0
  4513.  
  4514. The dspCLRemove command closes a connection end used as a connection listener.
  4515. You can release the memory you allocated for the connection control block if you
  4516. do not intend to reopen the connection end. 
  4517.  
  4518. The ioResult parameter returns the result of the function; in the case that you
  4519. call the function asynchronously, the function sets this field to 1 as soon as
  4520. it begins execution, and changes the field to the actual result code when it
  4521. completes execution. The csCode parameter is the routine selector; you should
  4522. set this to dspCLRemove for this command. The ccbRefNum parameter is the
  4523. connection control block reference number that was returned by the dspCLInit
  4524. command. If the abort parameter is nonzero, ADSP cancels any outstanding
  4525. requests to send packets (such as the dspCLDeny command). 
  4526.  
  4527. Result codes
  4528. noErr          0  no error
  4529. errRefNum  –1280  bad connection reference number
  4530. _______________________________________________________________________________
  4531.  
  4532. æKY Maintaining…an…ADSP…Connection
  4533. æC »Maintaining an ADSP Connection                                       AppleTalk Manager
  4534. _______________________________________________________________________________
  4535.  
  4536. Once you have established a connection end and opened a connection, you must be
  4537. able to send and receive data over the connection. You can use the functions in
  4538. this section to
  4539.  
  4540.   •   determine the status of a connection
  4541.   •   read bytes from the connection end’s receive queue
  4542.   •   write bytes to the connection end’s send queue and transmit them to the
  4543.       remote connection end
  4544.   •   send an attention message to the remote connection end
  4545.   •   discard all data that has been sent but not yet delivered, and reset the
  4546.       connection
  4547.  
  4548. The parameter block for the dspStatus command looks like this:
  4549.  
  4550. Parameter block
  4551.   ¨  16  ioResult  word  result code 
  4552.   Æ  26  csCode  word  always dspStatus
  4553.   Æ  32  ccbRefNum  word  reference number of connection end
  4554.   ¨  34  statusCCB  pointer  pointer to connection control block
  4555.   ¨  38  sendQPending  word  bytes waiting to be sent or 
  4556.           acknowledged
  4557.   ¨  40  sendQFree  word  available send queue in bytes
  4558.   ¨  42  recvQPending  word  bytes waiting to be read from queue
  4559.   ¨  44  recvQFree  word  available receive queue in bytes 
  4560.  
  4561. The dspStatus command returns the number of bytes waiting to be read and sent
  4562. and the space available in the send and receive queues. This function also
  4563. returns a pointer to the connection control block, which contains information
  4564. about the state of the connection end and about connection events received by
  4565. the connection end. The connection control block is described in “The ADSP
  4566. Connection Control Block” earlier in this chapter.
  4567.  
  4568. The ioResult parameter returns the result of the function; in the case that you
  4569. call the function asynchronously, the function sets this field to 1 as soon as
  4570. it begins execution, and changes the field to the actual result code when it
  4571. completes execution. The csCode parameter is the routine selector; you should
  4572. set this to dspStatus for this command. The ccbRefNum parameter is the
  4573. connection control block reference number that was returned by the dspInit
  4574. command. The statusCCB parameter returns a pointer to the connection control
  4575. block.
  4576.  
  4577. The sendQPending parameter indicates the number of bytes of data in the send
  4578. queue, including one byte for each end-of-message (EOM) indicator in the send
  4579. queue. (ADSP counts one byte for each EOM, even though there is no actual data
  4580. corresponding to the end-of-message indicator.) The send queue contains all data
  4581. that has been sent to ADSP for transmission that has not yet been acknowledged.
  4582. Some of the data in the send queue might have already been transmitted, but ADSP
  4583. retains it in the send queue until the remote connection end acknowledges its
  4584. receipt in case the data has to be retransmitted. The sendQFree parameter
  4585. indicates the buffer space available for additional data in the send queue, in
  4586. bytes. 
  4587.  
  4588. The recvQPending parameter indicates the number of bytes in the receive queue,
  4589. including one byte for each EOM if the end-of-message bit is set in an ADSP
  4590. packet header. The receive queue contains all of the data that has been received
  4591. by the connection end but not yet read by the connection end’s client. The
  4592. recvQFree parameter indicates the buffer space available for additional data in
  4593. the receive queue, in bytes.
  4594.  
  4595. Result codes
  4596. noErr          0  no error
  4597. errRefNum  –1280  bad connection reference number
  4598.  
  4599. The parameter block for the dspRead command looks like this:
  4600.  
  4601. Parameter block
  4602.   ¨  16  ioResult  word  result code 
  4603.   Æ  26  csCode  word  always dspRead
  4604.   Æ  32  ccbRefNum  word  reference number of connection end
  4605.   Æ  34  reqCount  word  requested number of bytes
  4606.   ¨  36  actCount  word  actual number of bytes read
  4607.   Æ  38  dataPtr  pointer  pointer to data buffer
  4608.   ¨  42  eom  byte  1 if end-of-message; 0 otherwise
  4609.  
  4610. The dspRead command reads bytes from the connection end’s receive queue and
  4611. places them in a buffer that you specify. You can continue to read bytes as long
  4612. as there is data in the receive queue, even after you or the remote end have
  4613. called the dspClose or dspRemove commands. The dspRead command completes
  4614. execution when it has read the number of bytes you specify, or when it
  4615. encounters an end-of-message (that is, the last byte of data in an ADSP packet
  4616. that has the end-of-message bit set in the packet header).
  4617.  
  4618. You can call the dspStatus command to determine the number of bytes remaining to
  4619. be read from the read queue, or you can continue to call the dspRead command
  4620. until the actCount and eom parameters both return 0.
  4621.  
  4622. The ioResult parameter returns the result of the function; in the case that you
  4623. call the function asynchronously, the function sets this field to 1 as soon as
  4624. it begins execution, and changes the field to the actual result code when it
  4625. completes execution. The csCode parameter is the routine selector; you should
  4626. set this to dspRead for this command. The ccbRefNum parameter is the connection
  4627. control block reference number that was returned by the dspInit command. 
  4628. You specify the number of bytes to read with the reqCount parameter, and use the
  4629. dataPtr parameter to provide a pointer to the buffer into which ADSP should
  4630. place the data. ADSP returns the actual number of bytes read in the actCount
  4631. parameter. If the last byte read constitutes an end-of-message, ADSP sets the
  4632. eom parameter to 1.
  4633.  
  4634. Result codes
  4635. noErr            0  no error
  4636. errFwdReset  –1275  read terminated by forward reset
  4637. errState     –1278  state isn’t open, closing, or closed
  4638. errAborted   –1279  request aborted by dspRemove or dspClose command
  4639. errRefNum    –1280  bad connection reference number
  4640.  
  4641. The parameter block for the dspWrite command looks like this:
  4642.  
  4643. Parameter block
  4644.   ¨  16  ioResult  word  result code 
  4645.   Æ  26  csCode  word  always dspWrite
  4646.   Æ  32  ccbRefNum  word  reference number of connection end
  4647.   Æ  34  reqCount  word  requested number of bytes
  4648.   ¨  36  actCount  word  actual number of bytes written
  4649.   Æ  38  dataPtr  pointer  pointer to data buffer
  4650.   Æ  42  eom  byte  1 if end of message; 0 otherwise
  4651.   Æ  43  flush  byte  1 to send data now; 0 otherwise
  4652.  
  4653. The dspWrite command writes bytes into the connection end’s send queue. The send
  4654. queue contains all data that has been sent to ADSP for transmission that has not
  4655. yet been acknowledged. Some of the data in the send queue might have already
  4656. been transmitted, but ADSP retains it in the send queue until the remote
  4657. connection end acknowledges its receipt in case the data has to be
  4658. retransmitted. The dspWrite command completes execution when it has copied all
  4659. of the data from the data buffer into the ADSP send queue.
  4660.  
  4661. ADSP transmits the data in the send queue when the remote connection end has
  4662. room to accept the data and one of the following conditions occurs:
  4663.  
  4664.   •   You call the dspWrite command with the flush parameter set to a nonzero
  4665.       number.
  4666.  
  4667.   •   The number of bytes in the send queue equals or exceeds the blocking
  4668.       factor; you use the sendBlocking parameter to the dspOptions command to
  4669.       set the blocking factor.
  4670.  
  4671.   •   The send timer expires.
  4672.  
  4673.   •   A connection event requires that the local connection end send an
  4674.       acknowlegment packet to the remote connection end.
  4675.  
  4676. The ioResult parameter returns the result of the function; in the case that you
  4677. call the function asynchronously, the function sets this field to 1 as soon as
  4678. it begins execution, and changes the field to the actual result code when it
  4679. completes execution. The csCode parameter is the routine selector; you should
  4680. set this to dspWrite for this command. The ccbRefNum parameter is the connection
  4681. control block reference number that was returned by the dspInit command. 
  4682.  
  4683. You specify the number of bytes to write with the reqCount parameter, and use
  4684. the dataPtr parameter to provide a pointer to the buffer from which ADSP should
  4685. read the data. The dspWrite command returns the actual number of bytes written
  4686. in the actCount parameter. If the last byte written constitutes an
  4687. end-of-message, set the eom parameter to 1. You can also set the reqCount
  4688. parameter to 0 and the eom parameter to 1 to indicate that the last byte you
  4689. sent the previous time you called the dspWrite command was the end of the
  4690. message. 
  4691.  
  4692. You can set the reqCount parameter to a value larger than the size of the send
  4693. queue. If you do so, the dspWrite command writes as much data as it can into the
  4694. send queue, sends the data and waits for acknowledgement, and then writes more
  4695. data into the send queue until it has written the amount of data you requested.
  4696. In this case, the function does not complete execution until it has finished
  4697. writing all of the data into the send queue. 
  4698.  
  4699. The high-order bits of the eom parameter are reserved for use by ADSP; you must
  4700. leave these bits equal to 0.
  4701.  
  4702. Set the flush parameter to 1 to cause ADSP to immediately transmit any data in
  4703. the send queue that has not already been transmitted. Set the flush parameter to
  4704. 0 to allow data to accumulate in the send queue until another condition occurs
  4705. that causes data to be transmitted. The high-order bits of the flush parameter
  4706. are reserved for use by ADSP; you must leave these bits equal to 0.
  4707.  
  4708. Result codes
  4709. noErr           0  no error
  4710. errState    –1278  connection is not open
  4711. errAborted  –1279  request aborted by dspRemove or dspClose command
  4712. errRefNum   –1280  bad connection reference number
  4713.  
  4714. The parameter block for the dspAttention command looks like this:
  4715.  
  4716. Parameter block
  4717.   ¨  16  ioResult  word  result code 
  4718.   Æ  26  csCode  word  always dspAttention
  4719.   Æ  32  ccbRefNum  word  reference number of connection end
  4720.   Æ  34  attnCode  word  client attention code
  4721.   Æ  36  attnSize  word  size of attention data in bytes
  4722.   Æ  38  attnData  pointer  pointer to attention data
  4723.  
  4724. The dspAttention command sends an attention code and an attention message to the
  4725. remote connection end. Attention codes and attention messages can have any
  4726. meaning that your application and the application at the remote connection end
  4727. both recognize. The purpose of attention codes and messages is to allow clients
  4728. of ADSP to send messages outside the normal data stream. For example, if a
  4729. connection end on a mainframe computer is connected to several connection ends
  4730. in Macintosh computers being used as remote terminals, the mainframe computer
  4731. might wish to inform the remote terminals that all connections will be
  4732. terminated in ten minutes. The mainframe application could send an attention
  4733. message to each of the remote terminals informing them of this fact, and the
  4734. terminal emulation programs in the Macintosh computers could then display an
  4735. alert message on the screen so that the users could prepare to shut down.
  4736.  
  4737. The ioResult parameter returns the result of the function; in the case that you
  4738. call the function asynchronously, the function sets this field to 1 as soon as
  4739. it begins execution, and changes the field to the actual result code when it
  4740. completes execution. The csCode parameter is the routine selector; you should
  4741. set this to dspAttention for this command. The ccbRefNum parameter is the
  4742. connection control block reference number that was returned by the dspInit
  4743. command. 
  4744.  
  4745. The attnCode parameter is the attention code that you wish to send to the remote
  4746. connection end. You can use any value from $0000 through $EFFF for the attention
  4747. code. The values $F000 through $FFFF are reserved for use by ADSP. The attnSize
  4748. parameter is the size in bytes of the attention message you wish to send, and
  4749. the attnData parameter provides a pointer to the attention message. The
  4750. attention message can be any size from 0 through 570 bytes. There are no
  4751. restrictions on the content of the attention message.
  4752.  
  4753. Result codes
  4754. noErr             0  no error
  4755. errAttention  –1276  attention message too long
  4756. errState      –1278  connection is not open
  4757. errAborted    –1279  request aborted by dspRemove or dspClose command
  4758. errRefNum     –1280  bad connection reference number
  4759.  
  4760. The parameter block for the dspReset command looks like this:
  4761.  
  4762. Parameter block
  4763.   ¨  16  ioResult  word  result code 
  4764.   Æ  26  csCode  word  always dspReset
  4765.   Æ  32  ccbRefNum  word  reference number of connection end
  4766.  
  4767. The dspReset command causes ADSP to discard all data in the send queue, all data
  4768. in transit to the remote connection end, and all data in the remote connection
  4769. end’s receive queue that the client has not yet read. This process is known as a
  4770. forward reset. ADSP then resynchronizes the connection. You can determine that
  4771. your connection end has received a forward reset and has discarded all data in
  4772. the receive queue by checking the eFwdReset flag in the userFlags field of the
  4773. connection control block. The connection control block is described in “The ADSP
  4774. Connection Control Block” earlier in this chapter. 
  4775.  
  4776. The ioResult parameter returns the result of the function; if you call the
  4777. function asynchronously, the function sets this field to 1 as soon as it begins
  4778. execution, and changes the field to the actual result code when it completes
  4779. execution. The csCode parameter is the routine selector; you should set this to
  4780. dspReset for this command. The ccbRefNum parameter is the connection control
  4781. block reference number that was returned by the dspInit command. 
  4782.  
  4783. Result codes
  4784. noErr           0  no error
  4785. errState    –1278  connection is not open
  4786. errAborted  –1279  request aborted by dspRemove or dspClose command
  4787. errRefNum   –1280  bad connection reference number
  4788. _______________________________________________________________________________
  4789.  
  4790. æKY The….ATP…Driver
  4791. æC »THE .ATP DRIVER                                                      AppleTalk Manager
  4792. _______________________________________________________________________________
  4793.  
  4794. AppleTalk Phase 2 includes two changes to the .ATP driver: you can now cancel
  4795. all calls to the ATPGetRequest function that are pending execution, and you can
  4796. now set the release timer for ATP exactly-once (XO) service to one of five
  4797. different values. 
  4798. _______________________________________________________________________________
  4799.  
  4800. æKY Canceling…All…Calls…to…the…ATPGetRequest…Function
  4801. æC »Canceling All Calls to the ATPGetRequest Function                    AppleTalk Manager
  4802. _______________________________________________________________________________
  4803.  
  4804. The ATPGetRequest function sets a socket to receive a request sent by another
  4805. socket. If you call the ATPGetRequest function asynchronously, you can have
  4806. several calls to the function simultaneously pending execution. The
  4807. ATPKillAllGetReq function cancels all calls to the ATPGetRequest function
  4808. pending for a specific socket without closing the socket. 
  4809.  
  4810. FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  4811.  
  4812. Parameter block
  4813.   Æ  26  csCode  word  always ATPKillAllGetReq
  4814.   Æ  28  atpSocket  byte  socket for which to cancel all calls to ATPGetRequest
  4815.  
  4816. The ATPKillAllGetReq function cancels all pending asynchronous calls to the
  4817. ATPGetRequest function for the socket you specify with the atpSocket parameter.
  4818. Unlike the ATPCloseSocket function, the ATPKillAllGetReq function does not close
  4819. the socket. You should call the ATPKillAllGetReq function before closing a
  4820. socket. The csCode parameter is a routine selector, automatically set by the MPW
  4821. interface. It is always equal to ATPKillAllGetReq for this function.
  4822.  
  4823. Result codes
  4824. noErr           0  no error
  4825. cbNotFound  –1102  control block not found; no pending asynchronous calls
  4826. _______________________________________________________________________________
  4827.  
  4828. æKY Setting…the…Timeout…Value…For…the…ATP…Release…Timer
  4829. æC »Setting the Timeout Value For the ATP Release Timer                  AppleTalk Manager
  4830. _______________________________________________________________________________
  4831.  
  4832. The .ATP driver maintains a timer, called the release timer, for each call to
  4833. the PSendResponse function that is part of an exactly-once transaction. If the
  4834. timer expires before the transaction is complete (that is, before the socket
  4835. receives the transaction release packet), the driver completes the PSendResponse
  4836. function. Before AppleTalk Phase 2, the release timer was always set to 30
  4837. seconds. To set the other connection end’s release timer to another value, set
  4838. bit 2 of the atpFlags field in the parameter block for the PSendRequest or the
  4839. PNSendRequest function and add a new field to the parameter block at offset 50:
  4840. the TRelTime field. The lower three bits of the TRelTime field indicate the time
  4841. to which the release timer is to be set, as follows:
  4842.  
  4843. TRelTime Field  Setting of Release Timer
  4844. 000             30 seconds
  4845. 001             1 minute
  4846. 010             2 minutes
  4847. 011             4 minutes
  4848. 100             8 minutes
  4849.  
  4850. Note:  The nodes at both ends of the ATP connection must be running AppleTalk
  4851. Phase 2 drivers for this feature to work.
  4852.  
  4853. Exactly-once service, the release timer, and the PSendRequest function are
  4854. described in the AppleTalk Manager chapter of Volume II. The ATP parameter block
  4855. and the PSendRequest function are described in the AppleTalk Manager chapter of
  4856. Volume V.
  4857.  
  4858. _______________________________________________________________________________
  4859.  
  4860. æKY The….XPP…Driver
  4861. æC »THE .XPP DRIVER                                                      AppleTalk Manager
  4862. _______________________________________________________________________________
  4863.  
  4864. The .XPP driver provides these functions that return information about zones:
  4865.  
  4866.   •   The GetMyZone function returns the AppleTalk zone name of the node on
  4867.       which your application is running.
  4868.  
  4869.   •   The GetLocalZones function returns a list of zone names on the network
  4870.       that includes the node on which your application is running.
  4871.  
  4872.   •   The GetZoneList function returns a complete list of zones on the internet.
  4873.  
  4874. Note:  Before the AppleTalk Phase 2 version of the .XPP driver, you had to use
  4875. ATP to obtain zone information and request it directly from a router. The ZIP
  4876. functions provided by the new version of the .XPP driver make it much easier for
  4877. you to obtain this information. To ensure compatibility with future versions of
  4878. AppleTalk, you should always use the functions described in this section to
  4879. obtain zone information.  
  4880.  
  4881. The .XPP driver uses a parameter block defined by the xCallParam record for the
  4882. GetMyZone, GetLocalZones, and GetZoneList functions.
  4883.  
  4884. xCallParam = PACKED RECORD
  4885.   qLink:         QElemPtr;  {next queue entry}
  4886.   qType:         INTEGER;  {queue type}
  4887.   ioTrap:        INTEGER;  {routine trap}
  4888.   ioCmdAddr:     Ptr;      {routine address}
  4889.   ioCompletion:  ProcPtr;  {completion routine}
  4890.   ioResult:      OsErr;    {result code}
  4891.   ioNamePtr:     StringPtr;{used only for Open routine}
  4892.   ioVRefNum:     INTEGER;  {volume reference number}
  4893.   ioRefNum:      INTEGER;  {driver reference number}
  4894.   csCode:        INTEGER;  {primary command code}
  4895.   xppSubCode:    INTEGER;  {secondary command code}
  4896.   xppTimeOut:    Byte;     {timeout period for .XPP}
  4897.   xppRetry:      Byte;     {retry count}
  4898.   filler:        INTEGER;  {reserved}
  4899.   zipBuffPtr:    Ptr;      {returned zone names}
  4900.   zipNumZones:   INTEGER;  {number of zones returned}
  4901.   zipLastFlag:   Byte;     {nonzero when all zone names have been returned}
  4902.   filler        Byte;    {reserved}
  4903.   zipInfoField:  PACKED ARRAY[1..70] of Byte {reserved for use by .XPP}
  4904. END;
  4905.  
  4906. XCallParamPtr = ^XCallParam;
  4907.  
  4908. As for all other AppleTalk Manager preferred interface functions, the MPW
  4909. interface calls the Device Manager PBControl function to implement these ZIP
  4910. protocol functions. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and
  4911. ioVRefNum fields are filled in by the Device Manager; your application should
  4912. not have to set or read these parameters. The ioResult parameter returns the
  4913. result of the function; in the case that you call the function asynchronously,
  4914. the Device Manager sets this field to 1 as soon as you call the function, and
  4915. changes the field to the actual result code when the function completes
  4916. execution. The ioCompletion parameter is a pointer to a completion routine that
  4917. you can provide; the Device Manager calls your completion routine when it
  4918. completes execution of the PBControl function. If you are not providing a
  4919. completion routine, specify NIL for this field. The ioRefNum, csCode, and
  4920. xppSubCode fields specify the driver and the command to be executed; the MPW
  4921. Pascal interface fills in these fields for you.
  4922.  
  4923. _______________________________________________________________________________
  4924.  
  4925. æKY Using…the….XPP…Driver…to…Obtain…Zone…Information
  4926. æC »Using the .XPP Driver to Obtain Zone Information                     AppleTalk Manager
  4927. _______________________________________________________________________________
  4928.  
  4929. The Zone Information Protocol obtains the zone information by using the
  4930. AppleTalk Transaction Protocol to send an information request to a router. The
  4931. xppTimeOut field specifies the amount of time, in seconds, that the .ATP driver
  4932. should wait between attempts to obtain the data. The xppRetry field specifies
  4933. the number of times the .ATP driver should attempt to obtain the data before
  4934. returning the reqFailed (request failed) result code. 
  4935.  
  4936. The zipBuffPtr field is a pointer to a data buffer that you must allocate. This
  4937. buffer must be 578 bytes for the GetZoneList and GetLocalZones functions and 33
  4938. bytes for the GetMyZone function. The Zone Information Protocol returns the zone
  4939. names (as a packed array of packed Pascal strings) into this buffer. The
  4940. zipNumZones field returns the actual number of zone names that ZIP placed in the
  4941. buffer. You must set the zipLastFlag field to 0 before you execute the
  4942. GetZoneList or GetLocalZones functions. If the zipLastFlag parameter is still 0
  4943. when the command has completed execution, then the ZIP is waiting to return more
  4944. zone names. In this case you must empty the buffer (or allocate a new one) and
  4945. call the GetZoneList or GetLocalZones function again immediately. When there are
  4946. no more zone names to send, ZIP sets the zipLastFlag field to a nonzero value.
  4947.  
  4948. The zipInfoField field is a 70-byte data buffer that you must allocate for use
  4949. by the .XPP driver. The first time you call any of these functions, you must set
  4950. the first word of this field to 0. You must not change any values in this field
  4951. subsequently.
  4952.  
  4953. Listing 29-5 illustrates the use of the GetZoneList function. The GetLocalZones
  4954. function operates in exactly the same fashion.
  4955.  
  4956. Listing 29-5.  Using the GetZoneList function (TO BE PROVIDED)
  4957.  
  4958. Listing 29-6 illustrates the use of the GetMyZone function. 
  4959.  
  4960. Listing 29-6.  Using the GetMyZone function (TO BE PROVIDED)
  4961. _______________________________________________________________________________
  4962.  
  4963. æKY XPP…Driver…Routines
  4964. æC »XPP Driver Routines                                                  AppleTalk Manager
  4965. _______________________________________________________________________________
  4966.  
  4967. The .XPP driver provides three functions that obtain information about zones.
  4968. All three functions use the Zone Information Protocol to return the names of
  4969. zones: The GetMyZone function returns the AppleTalk zone name of the node on
  4970. which your application is running; the GetLocalZones function returns a list of
  4971. zone names on the network that includes the node on which your application is
  4972. running; and the GetZoneList function returns a complete list of zones on the
  4973. internet.
  4974.  
  4975. Assembly-language note:  The .XPP driver functions all use the same value
  4976. (xCall, which is equal to 246) for the csCode parameter to the xCallParam
  4977. parameter block. The xCall routine uses the value of the xppSubCode parameter to
  4978. distinguish between the functions, as follows:
  4979.  
  4980. Function        xppSubCode      Value
  4981. GetMyZone       getMyZone       7
  4982. GetLocalZones   getLocalZones   5
  4983. GetZoneList     getZoneList     6
  4984.  
  4985. FUNCTION GetMyZone (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  4986.  
  4987. Parameter block
  4988.   ¨  16  ioResult  word  result code 
  4989.   Æ  26  csCode  word  routine selector; always xCall
  4990.   Æ  28  xppSubCode  word  routine selector; getMyZone
  4991.   Æ  30  xppTimeOut  byte  retry interval in seconds
  4992.   Æ  31  xppRetry  byte  retry count
  4993.   Æ  34  zipBuffPtr  long  pointer to data buffer
  4994.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  4995.  
  4996. The GetMyZone function returns only the zone name of the node on which your
  4997. application is running.
  4998.  
  4999. The ioResult parameter returns the result of the function; if you call the
  5000. function asynchronously, the function sets this field to 1 as soon as it begins
  5001. execution, and changes the field to the actual result code when it completes
  5002. execution. The csCode and xppSubCode parameters are routine selectors and are
  5003. automatically set by the MPW interface to xCall and getMyZone for this function.
  5004. The xppTimeOut field specifies the amount of time, in seconds, that the .ATP
  5005. driver should wait between attempts to obtain the data. A value of 3 or 4 for
  5006. the xppTimeOut field generally gives good results. The xppRetry field specifies
  5007. the number of times the .ATP driver should attempt to obtain the data before
  5008. returning the ReqFailed (request failed) result code. A value of 3 or 4 for the
  5009. xppRetry field usually works well.
  5010.  
  5011. The zipBuffPtr is a pointer to a 33-byte data buffer that you must allocate. The
  5012. Zone Information Protocol returns the zone name into this buffer as a Pascal
  5013. string. The zipInfo field is a 70-byte data buffer that you must allocate for
  5014. use by ZIP. You must set the first word of this buffer to 0 before you call the
  5015. GetMyZone function.
  5016.  
  5017. Result codes
  5018. noErr          0  no error
  5019. noBridgeErr  –93  no router is available
  5020. reqFailed  –1096  Request to contact router failed; retry count exceeded 
  5021.  
  5022. FUNCTION GetLocalZones (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  5023.  
  5024. Parameter block
  5025.   ¨  16  ioResult  word  result code 
  5026.   Æ  26  csCode  word  routine selector; always xCall
  5027.   Æ  28  xppSubCode  word  routine selector; getLocalZones
  5028.   Æ  30  xppTimeOut  byte  retry interval in seconds
  5029.   Æ  31  xppRetry  byte  retry count
  5030.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  5031.   ¨  38  zipNumZones  word  number of names returned
  5032.   ¨  40  zipLastFlag  byte  nonzero if no more names
  5033.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  5034.  
  5035. The GetLocalZones function returns a list of all the zone names on the local
  5036. network; that is, the network that includes the node on which your application
  5037. is running.
  5038.  
  5039. The ioResult parameter returns the result of the function; if you call the
  5040. function asynchronously, the function sets this field to 1 as soon as it begins
  5041. execution, and changes the field to the actual result code when it completes
  5042. execution. The csCode and xppSubCode parameters are routine selectors and are
  5043. automatically set by the MPW interface to xCall and getLocalZones for this
  5044. function. The xppTimeOut field specifies the amount of time, in seconds, that
  5045. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  5046. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  5047. specifies the number of times the .ATP driver should attempt to obtain the data
  5048. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  5049. for the xppRetry field usually works well.
  5050.  
  5051. The zipBuffPtr is a pointer to a 578-byte data buffer that you must allocate.
  5052. The Zone Information Protocol returns the zone names into this buffer as a
  5053. packed array of packed Pascal strings. The zipNumZones parameter returns the
  5054. number of zone names that ZIP placed in the data buffer. 
  5055.  
  5056. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  5057. for your network. If the zipLastFlag field is still 0 when the GetLocalZones
  5058. function has completed execution, you must empty the data buffer pointed to by
  5059. the zipBuffPtr parameter and immediately call the GetLocalZones function again
  5060. without changing the value in the zipInfoField parameter. The zipInfofield
  5061. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  5062. must set the first word of this buffer to 0 before you call the GetLocalZones
  5063. function the first time, and not change the contents of this field thereafter.
  5064.  
  5065. FUNCTION GetZoneList (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  5066.  
  5067. Parameter block
  5068.   ¨  16  ioResult  word  result code 
  5069.   Æ  26  csCode  word  routine selector; always xCall
  5070.   Æ  28  xppSubCode  word  routine selector; getZoneList
  5071.   Æ  30  xppTimeOut  byte  retry interval in seconds
  5072.   Æ  31  xppRetry  byte  retry count
  5073.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  5074.   ¨  38  zipNumZones  word  number of names returned
  5075.   ¨  40  zipLastFlag  byte  nonzero if no more names
  5076.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  5077.  
  5078. The GetZoneList function returns a complete list of all the zone names on the
  5079. internet. Use the GetLocalZones function to obtain a list of only the zone names
  5080. on the local network. 
  5081.  
  5082. The ioResult parameter returns the result of the function; if you call the
  5083. function asynchronously, the function sets this field to 1 as soon as it begins
  5084. execution, and changes the field to the actual result code when it completes
  5085. execution. The csCode and xppSubCode parameters are routine selectors and are
  5086. automatically set by the MPW interface to xCall and getZoneList for this
  5087. function. The xppTimeOut field specifies the amount of time, in seconds, that
  5088. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  5089. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  5090. specifies the number of times the .ATP driver should attempt to obtain the data
  5091. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  5092. for the xppRetry field usually works well.
  5093.  
  5094. The zipBuffPtr is a pointer to a 578-byte data buffer that you must allocate.
  5095. The Zone Information Protocol returns the zone names into this buffer as Pascal
  5096. strings. The zipNumZones parameter returns the number of zone names that ZIP
  5097. placed in the data buffer. 
  5098.  
  5099. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  5100. for the internet. If the zipLastFlag field is still 0 when the GetZoneList
  5101. function has completed execution, you must empty the data buffer pointed to by
  5102. the zipBuffPtr parameter and immediately call the GetZoneList function again
  5103. without changing the value in the zipInfoField parameter. The zipInfofield
  5104. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  5105. must set the first word of this buffer to 0 before you call the GetZoneList
  5106. function the first time, and not change the contents of this field thereafter.
  5107.  
  5108. _______________________________________________________________________________
  5109.  
  5110. æKY The….ENET…Driver
  5111. æC »THE .ENET DRIVER                                                     AppleTalk Manager
  5112. _______________________________________________________________________________
  5113.  
  5114. The .ENET driver is an Ethernet driver for the EtherTalk NuBus card that is
  5115. manufactured by Apple Computer, Inc. The .ENET driver is normally called by the
  5116. AppleTalk Manager through the EtherTalk 'adev' file when the user has selected
  5117. EtherTalk from the Network control panel. You can write your own protocol stack
  5118. or application that uses the .ENET driver directly, rather than through
  5119. AppleTalk. This section describes how to open the .ENET driver, how to send data
  5120. to it directly for transmission over the Ethernet network, and how to write a
  5121. protocol handler to receive data from the network.
  5122.  
  5123. If you write an Ethernet driver for use with your own Ethernet NuBus card, you
  5124. should provide the features and functions described in this chapter and should
  5125. name your driver .ENET. If you write an Ethernet driver for use with a non-NuBus
  5126. network interface (such as an Ethernet card for the Macintosh SE/30 or an
  5127. Ethernet connection through the SCSI port), you should provide the features and
  5128. functions described in this chapter for the .ENET driver and should name your
  5129. driver .ENET0. If you do so, any software written to use the .ENET driver should
  5130. work with your driver.
  5131.  
  5132. _______________________________________________________________________________
  5133.  
  5134. æKY Changing…the…Ethernet…Hardware…Address
  5135. æC »Changing the Ethernet Hardware Address                               AppleTalk Manager
  5136. _______________________________________________________________________________
  5137.  
  5138. Each Ethernet NuBus card or other Ethernet hardware interface device contains a
  5139. unique 6-byte hardware address assigned by the manufacturer of the device. The 
  5140. .ENET driver normally uses this address to determine whether to receive a
  5141. packet. To change the hardware address for your node, place in the System file a
  5142. resource of type 'eadr' with a resource ID equal to the slot number of the
  5143. Ethernet NuBus card. If the Ethernet device is not a NuBus card (it might be a
  5144. slot card in a Macintosh SE/30, for example), use a resource ID of 0. 
  5145.  
  5146. The 'eadr' resource consists only of a 6-byte number. Do not use the broadcast
  5147. address or a multicast address for this number. (The broadcast address is
  5148. $FF-FF-FF-FF-FF-FF. A multicast address is any Ethernet address in which the
  5149. low-order bit of the high-order byte is set to 1.) When you open the .ENET
  5150. driver, it looks for an 'eadr' resource. If it finds one, the driver substitutes
  5151. the number in this resource for the Ethernet hardware address and uses it until
  5152. the driver is closed or reset. 
  5153.  
  5154. Note:  To avoid address collisions, you should never arbitrarily change the
  5155. Ethernet hardware address. This feature should be used only by a system
  5156. adiministrator who can keep track of all the Ethernet addresses in the system.
  5157.  
  5158. _______________________________________________________________________________
  5159.  
  5160. æKY Opening…the….ENET…Driver
  5161. æC »Opening the .ENET Driver                                             AppleTalk Manager
  5162. _______________________________________________________________________________
  5163.  
  5164. Before you use the OpenSlot function to open the .ENET driver, you must
  5165. determine which NuBus slots contain EtherTalk cards. The OpenSlot function is
  5166. described in the Device Manager chapter of Volume V. Use the GetsRsrc function
  5167. described in the Slot Manager chapter of this volume to determine which NuBus
  5168. slots contain cards and the type of each NuBus card installed. EtherTalk NuBus
  5169. cards return the string CatNetwork in the field spCategory of the GetsRsrc
  5170. function parameter block, and return the string TypEthernet in the field spType.
  5171.  
  5172. Listing 29-7 illustrates the use of the GetsRsrc function and the OpenSlot
  5173. function to open the .ENET driver.
  5174.  
  5175. Listing 29-7.  Finding an EtherTalk card and opening the .ENET Driver (TO BE
  5176. PROVIDED)
  5177. _______________________________________________________________________________
  5178.  
  5179. æKY Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  5180. æC »Using a Write-Data Structure to Transmit Ethernet Data               AppleTalk Manager
  5181. _______________________________________________________________________________
  5182.  
  5183. When you use the EWrite function to send data to the .ENET driver for
  5184. transmission over the Ethernet network, you provide a pointer to a write-data
  5185. structure (Figure 29-4). A write-data structure contains a series of pairs of
  5186. length words and pointers. Each pair indicates the length and location of a
  5187. portion of the data that constitutes the packet to be sent over the network. The
  5188. first length-pointer pair points to a 14-byte header block, which starts with
  5189. the destination node hardware address. Note that this is not the AppleTalk
  5190. address, but is the hardware address of the destination node. If you are calling
  5191. the .ENET driver directly, you must obtain the Ethernet address of the
  5192. destination node yourself; AppleTalk cannot provide it.
  5193.  
  5194. The next 6 bytes of the header block are reserved for use by the .ENET driver.
  5195. These bytes are followed by the 2-byte Ethernet protocol type. Data may follow
  5196. the header block; all other length-pointer pairs point to data. The write-data
  5197. structure terminates with a NIL word.
  5198.  
  5199. ø 29.3  Ethernet Write-Data Structure
  5200.  
  5201. When you first open the .ENET driver, it allocates a 768-byte buffer that it
  5202. uses for transmitting data packets. This buffer is large enough to hold the
  5203. largest EtherTalk packet, which is 617 bytes in size. If you want to transmit
  5204. data packets larger than 768 bytes, call the ESetGeneral function. The .ENET
  5205. driver then allocates a large enough data buffer to send packets up to 1514
  5206. bytes in size.
  5207.  
  5208. Listing 29-8 defines an Ethernet write-data structure and then calls the EWrite
  5209. function to send a data packet over Ethernet.
  5210.  
  5211. Listing 29-8.  Sending a Data Packet Over Ethernet (TO BE PROVIDED)
  5212. _______________________________________________________________________________
  5213.  
  5214. æKY Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  5215. æC »Using the Default Ethernet Protocol Handler to Read Data             AppleTalk Manager
  5216. _______________________________________________________________________________
  5217.  
  5218. When the EtherTalk Nubus card or other Ethernet hardware receives a data packet,
  5219. it generates an interrupt to the CPU. The interrupt handler in ROM determines
  5220. the source of the interrupt and calls the .ENET driver. The .ENET driver reads
  5221. the packet header to determine the protocol type of the data packet and checks
  5222. to see if any client has specified that protocol type in a call to the EAttachPH
  5223. function. If so, the client either specified a NIL pointer to a protocol
  5224. handler, or the client provided its own protocol handler. If the client
  5225. specified a NIL pointer, the .ENET driver uses its default protocol handler to
  5226. read the data. If no one has specified that protocol type in a call to the
  5227. EAttachPH function, the .ENET driver discards the data. The EAttachPH function
  5228. is described in 
  5229. “Attaching and Detaching an Ethernet Protocol Handler” later in this chapter.
  5230.  
  5231. The default protocol handler checks for an ERead function pending execution and
  5232. places the entire packet—including the packet header—into the buffer specified
  5233. by that function. The function returns the number of bytes actually read. If the
  5234. packet is larger than the data buffer, the ERead function places as much of the
  5235. packet as will fit into the buffer and returns the buf2SmallErr result code.
  5236.  
  5237. Call the ERead function asynchronously to await the next data packet. When the 
  5238. .ENET driver receives the data packet, it completes execution of the ERead
  5239. function and calls your completion routine. Your completion routine should call
  5240. the ERead function again so that there is always an ERead function pending
  5241. execution. If the .ENET driver receives a data packet with a protocol type for
  5242. which you specified the default protocol handler, but there is no ERead function
  5243. pending, the .ENET driver discards the packet.
  5244.  
  5245. You can have several asynchronous calls to the ERead function pending execution
  5246. simultaneously, as long as you use a different parameter block for each call.
  5247.  
  5248. Listing 29-9 defines a completion routine.
  5249.  
  5250. Listing 29-9.  Using the Default Ethernet Protocol Handler to Read Data (TO BE
  5251. PROVIDED)
  5252.  
  5253. _______________________________________________________________________________
  5254.  
  5255. æKY Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  5256. æC »Using Your Own Ethernet Protocol Handler to Read Data                AppleTalk Manager
  5257. _______________________________________________________________________________
  5258.  
  5259. If a client of the .ENET driver has used the EAttachPH function to provide a
  5260. pointer to its own protocol handler, the .ENET driver calls that protocol
  5261. handler, which must in turn call the .ENET driver’s ReadPacket and ReadRest
  5262. routines to read the data. Your protocol handler calls the .ENET driver’s
  5263. ReadPacket and ReadRest routines in essentially the same way as you call the
  5264. .MPP drivers ReadPacket and ReadRest routines (see the AppleTalk Manager chapter
  5265. of Volume II). The following sections describe the .ENET driver’s call to a
  5266. custom protocol handler and the ReadPacket and ReadRest routines.
  5267.  
  5268. Note:  Because an Ethernet protocol handler must read from and write to the 
  5269. CPU’s registers, you cannot write a protocol handler in Pascal. 
  5270. _______________________________________________________________________________
  5271.  
  5272. æKY How…the….ENET…Driver…Calls…Your…Protocol…Handler
  5273. æC »How the .ENET Driver Calls Your Protocol Handler                     AppleTalk Manager
  5274. _______________________________________________________________________________
  5275.  
  5276. You can provide an Ethernet protocol handler for a particular protocol type and
  5277. use the EAttachPH function to attach it to the .ENET driver. When the driver
  5278. receives an Ethernet packet, it reads the packet header into an internal buffer,
  5279. reads the protocol type, and calls the protocol handler for that protocol type.
  5280. The CPU is in interrupt mode and the registers are used as follows:
  5281.  
  5282. Registers on call to Ethernet protocol handler
  5283.  
  5284. A0
  5285. Reserved for internal use by the .ENET driver; you must preserve this register
  5286. until after the ReadRest routine has completed execution
  5287.  
  5288. A1
  5289. Reserved for internal use by the .ENET driver; you must preserve this register
  5290. until after the ReadRest routine has completed execution
  5291.  
  5292. A2  Free for your use
  5293.  
  5294. A3
  5295. Pointer to first byte past data-link header bytes (the first byte after the
  5296. 2-byte protocol-type field)
  5297.  
  5298. A4
  5299. Pointer to the ReadPacket routine; the ReadRest routine starts 2 bytes after the
  5300. start of the ReadPacket routine
  5301.  
  5302. A5
  5303. Free for your use until after the ReadRest routine has completed execution
  5304.  
  5305. D0  Free for your use
  5306.  
  5307. D1
  5308. Number of bytes in the Ethernet packet left to be read (that is, the number of
  5309. bytes following the Ethernet header) 
  5310.  
  5311. D2  Free for your use
  5312.  
  5313. D3  Free for your use
  5314.  
  5315. If your protocol handler processes more than one protocol type, you can read the
  5316. protocol-type field in the data-link header to determine the protocol type of
  5317. the packet. The protocol-type field starts 2 bytes before the address pointed to
  5318. by the A3 register. 
  5319.  
  5320. Note:  The source address starts 8 bytes before the address pointed to by the A3
  5321. register and the destination address starts 14 bytes before the address pointed
  5322. to by the A3 register.
  5323.  
  5324. If you know that the packet contains pad bytes and you know the actual size of
  5325. the data, you can reduce the number in the D1 register by the number of pad
  5326. bytes so that the .ENET driver can keep accurate track of the number of bytes
  5327. remaining to be read. In all other circumstances, you should not change the
  5328. value in the D1 register. 
  5329.  
  5330. After you have called the ReadRest routine, you can use registers A0 through A3
  5331. and D0 through D3 for your own use, and must preserve all other registers. You
  5332. cannot depend on having access to your application global variables.
  5333.  
  5334. _______________________________________________________________________________
  5335.  
  5336. æKY How…Your…Protocol…Handler…Calls…the….ENET…Driver
  5337. æC »How Your Protocol Handler Calls the .ENET Driver                     AppleTalk Manager
  5338. _______________________________________________________________________________
  5339.  
  5340. Your protocol handler must call the .ENET driver routines ReadPacket and
  5341. ReadRest to read the incoming data packet. You may call the ReadPacket routine
  5342. as many times as you like to read the data piece-by-piece into one or more data
  5343. buffers, but you must always use the ReadRest routine to read the final piece of
  5344. the data packet. The ReadRest routine restores the machine state (the stack
  5345. pointers, status register, and so forth) and checks for error conditions. 
  5346. Before you call the ReadPacket routine, you must allocate memory for a data
  5347. buffer and place a pointer to the buffer in the A3 register. You place the
  5348. number of bytes you want to read in the D3 register. You must not request more
  5349. bytes than remain in the data packet. 
  5350.  
  5351. To call the ReadPacket routine, execute a JSR instruction to the address in the
  5352. A4 register. The ReadPacket routine uses the registers as follows:
  5353.  
  5354. Registers on entry to the ReadPacket routine
  5355.  
  5356. A3  Pointer to a buffer to hold the data you want to read
  5357. D3  Number of bytes to read; must be nonzero
  5358.  
  5359. Registers on exit from the ReadPacket routine
  5360.  
  5361. A0  Unchanged
  5362. A1  Unchanged
  5363. A2  Unchanged
  5364. A3  Pointer to next byte to read (first byte after the last byte read)
  5365. D0  Changed
  5366. D1  Number of bytes left to be read
  5367. D2  Unchanged
  5368. D3  Equals 0 if requested number of bytes were read, nonzero if error
  5369.  
  5370. The ReadPacket routine indicates an error by clearing to 0 the zero (z) flag in
  5371. the status register. If the ReadPacket routine returns an error, you must
  5372. terminate execution of your protocol handler with an RTS instruction without
  5373. calling ReadPacket again or calling ReadRest at all.
  5374.  
  5375. Call the ReadRest routine to read the last portion of the data packet, or call
  5376. it after you have read all the data with ReadPacket routines and before you do
  5377. any other processing or terminate execution. You must provide in the A3 register
  5378. a pointer to a data buffer and must indicate in the D3 register the size of the
  5379. data buffer. If you have already read all of the data with calls to the
  5380. ReadPacket routine, you can specify a 0-size buffer.
  5381.  
  5382. †  Warning:  If you do not call the ReadRest routine after your last call to the
  5383. ReadPacket routine, the system will crash. Ê 
  5384.  
  5385. To call the ReadRest routine, execute a JSR instruction to an address 2 bytes
  5386. past the address in the A4 register. The ReadRest routine uses the registers as
  5387. follows:
  5388.  
  5389. Registers on entry to the ReadRest routine
  5390.  
  5391. A3  Pointer to a buffer to hold the data you want to read
  5392. D3  Size of the buffer (word length); may be 0
  5393.  
  5394. Registers on exit from the ReadRest routine
  5395.  
  5396. A0  Unchanged
  5397. A1  Unchanged
  5398. A2  Unchanged
  5399. A3  Pointer to first byte after the last byte read
  5400. D0  Changed
  5401. D1  Changed
  5402. D2  Unchanged
  5403. D3  Equals 0 if requested number of bytes were read; less than 0 if there was
  5404. more data left than would fit in buffer (extra data equals –D3 bytes); greater
  5405. than 0 if there was less data left than the size of the buffer (extra buffer
  5406. space equals D3 bytes)
  5407.  
  5408. If the buffer you provide is not large enough to hold the remaining bytes in the
  5409. packet, the ReadRest routine returns an error. The ReadRest routine indicates an
  5410. error by clearing to 0 the zero (z) flag in the status register. 
  5411.  
  5412. You must terminate execution of your protocol handler with an RTS instruction
  5413. whether or not the ReadRest routine returns an error.
  5414.  
  5415. _______________________________________________________________________________
  5416.  
  5417. æKY ENET…Driver…Routines
  5418. æC »ENET Driver Routines                                                 AppleTalk Manager
  5419. _______________________________________________________________________________
  5420.  
  5421. An application that uses AppleTalk Manager routines for network communications
  5422. can talk to whatever network the user has selected through the Network control
  5423. panel. However, you can choose to write an application that talks only to
  5424. Ethernet; in this case, your application has to address the Ethernet driver
  5425. directly. This section describes the functions that you can use to control the 
  5426. .ENET driver, the Ethernet driver provided with system software version 7.0.
  5427. Each.ENET driver function is of the form 
  5428.  
  5429. FUNCTION Efunc (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5430.  
  5431. where the thePBptr parameter is a pointer to the .ENET parameter block and the
  5432. async parameter is a Boolean that specifies whether the function is to be
  5433. executed synchronously or asynchronously. Set the async parameter to TRUE to
  5434. execute the function asynchronously.
  5435.  
  5436. The .ENET parameter block is defined as follows:
  5437.  
  5438. EParamBlock = PACKED RECORD
  5439.   qLink:   QElemPtr;  {next queue entry}
  5440.   qType:   INTEGER;  {queue type}
  5441.   ioTrap:   INTEGER;  {routine trap}
  5442.   ioCmdAddr:   Ptr;  {routine address}
  5443.   ioCompletion:   ProcPtr;  {completion routine}
  5444.   ioResult:   OsErr;  {result code}
  5445.   ioNamePtr:   StringPtr;  {driver name}
  5446.   ioVRefNum:   INTEGER;  {volume reference number}
  5447.   ioCRefNum:   INTEGER;  {driver reference number}
  5448.   csCode:   INTEGER;  {primary command code}
  5449.  
  5450.   CASE INTEGER OF
  5451.   EWrite,
  5452.   EAttachPH,
  5453.   EDetachPH,
  5454.   ERead,
  5455.   ERdCancel,
  5456.   EGetInfo,
  5457.   ESetGeneral:
  5458.     (
  5459.     EProtType:  INTEGER;  {Ethernet protocol type}
  5460.     EPointer:  Ptr;  {pointer; use depends on function}
  5461.     EBuffSize  INTEGER  {buffer size}
  5462.     EDataSize  INTEGER  {number of bytes read}
  5463.     );
  5464.  
  5465.   EAddMulti,
  5466.   EDelMulti:
  5467.     (
  5468.     EMultiAddr:  ?????;  {Multicast address}
  5469.     );
  5470. END;
  5471.  
  5472. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are
  5473. standard parameters provided by the Pascal or C interface; your application
  5474. should not have to set or read these parameters. The ioResult parameter returns
  5475. the result of the function; in the case that you call the function
  5476. asynchronously, the function sets this field to 1 as soon as it begins
  5477. execution, and changes the field to the actual result code when it completes
  5478. execution. The ioCompletion parameter is a pointer to a completion routine that
  5479. you can provide; the Device Manager calls your completion routine when it
  5480. completes execution of the function. If you are not providing a completion
  5481. routine, specify NIL for this field. The ioCRefNum and csCode fields specify the
  5482. driver and the command to be executed; the MPW Pascal interface fills in these
  5483. fields for you. The Control function is discussed in the Device Manager chapter
  5484. of Volume II.
  5485.  
  5486. The remaining parameters are used only for specific functions; all of these
  5487. parameters are described in the following sections.
  5488.  
  5489. For a general discussion of the use of the Ethernet driver, see “The .ENET
  5490. Driver” earlier in this chapter.
  5491.  
  5492. _______________________________________________________________________________
  5493.  
  5494. æKY Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  5495. æC »Attaching and Detaching an Ethernet Protocol Handler                 AppleTalk Manager
  5496. _______________________________________________________________________________
  5497.  
  5498. The functions in this section allow you to attach a protocol handler to the
  5499. .ENET driver, to specify which protocol handler the .ENET driver is to use for
  5500. each protocol type, and to detach a protocol handler that you previously
  5501. attached. The section “Using Your Own Ethernet Protocol Handler to Read Data”
  5502. earlier in this chapter, describes how to write and use Ethernet protocol
  5503. handlers.
  5504.  
  5505. FUNCTION EAttachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5506.  
  5507. Parameter block
  5508.   ¨  16  ioResult  word  result code 
  5509.   Æ  26  csCode  word  always EAttachPH
  5510.   Æ  28  EProtType  word  Ethernet protocol type
  5511.   Æ  30  EPointer  pointer  pointer to protocol handler
  5512.  
  5513. The EAttachPH function serves two purposes: You can use it to attach to the 
  5514. .ENET driver your own protocol handler for a specific protocol type; or you can
  5515. use it to specify that the .ENET driver should use the default protocol handler
  5516. for a particular protocol type. If you attach your own protocol handler, the 
  5517. .ENET driver calls that protocol handler each time it receives a packet with the
  5518. protocol type you specified. If you specify that the .ENET driver should use the
  5519. default protocol handler, then you can use the ERead command to read packets
  5520. with that protocol type. 
  5521.  
  5522. The ioResult parameter returns the result of the function; if you call the
  5523. function asynchronously, the function sets this field to 1 as soon as it begins
  5524. execution, and changes the field to the actual result code when it completes
  5525. execution. The csCode parameter is a routine selector that is set automatically
  5526. for you by the MPW interface; it is always equal to EAttachPH for this function.
  5527. You specify the protocol type in the EProtType parameter and provide a pointer
  5528. to the protocol handler in the EPointer parameter. If you specify NIL for the
  5529. EPointer parameter, then the .ENET driver uses the default protocol handler for
  5530. that protocol type. Specify 0 for the EProtType parameter to attach a protocol
  5531. handler for the IEEE 802.3 protocol, which uses protocol types 0 through $5DC.
  5532.  
  5533. Note:  In addition to using the EAttachPH function to install a protocol handler
  5534. for an Ethernet protocol type, you can use the L802Attach function to install a
  5535. protocol handler for an 802.2 protocol type. In the case of an 802.2 protocol
  5536. packet, the .ENET driver passes the packet to the LAP Manager 802.2 protocol
  5537. handler. If the packet has the protocol type you specified with the L802Attach
  5538. function, the 802.2 protocol handler passes the packet on to your protocol
  5539. handler. See “The LAP Manager 802.2 Protocol” earlier in this chapter, for more
  5540. information about IEEE 802.2 protocols.
  5541.  
  5542. Result codes
  5543. noErr         0  no error
  5544. LAPProtErr  –94  protocol handler is already attached or node’s protocol 
  5545.                  table is full
  5546.  
  5547. FUNCTION EDetachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5548.  
  5549. Parameter block
  5550.   ¨  16  ioResult  word  result code 
  5551.   Æ  26  csCode  word  always EDetachPH
  5552.   Æ  28  EProtType  word  Ethernet protocol type
  5553.  
  5554. The EDetachPH function detaches a protocol handler from the .ENET driver. Once
  5555. you have removed a protocol type from the node’s protocol table with this
  5556. command, the .ENET driver no longer delivers packets with that protocol type.
  5557. You specify the protocol type in the EProtType parameter.
  5558.  
  5559. The ioResult parameter returns the result of the function; if you call the
  5560. function asynchronously, the function sets this field to 1 as soon as it begins
  5561. execution, and changes the field to the actual result code when it completes
  5562. execution. The csCode parameter is a routine selector that is set automatically
  5563. for you by the MPW interface; it is always equal to EAttachPH for this function.
  5564.  
  5565. Result codes
  5566. noErr         0  no error
  5567. LAPProtErr  –94  no protocol handler attached
  5568. _______________________________________________________________________________
  5569.  
  5570. æKY Writing…and…Reading…Packets…Using…the…Default…Protocol…Handler
  5571. æC »Writing and Reading Packets Using the Default Protocol Handler       AppleTalk Manager
  5572. _______________________________________________________________________________
  5573.  
  5574. FUNCTION EWrite (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5575.  
  5576. Parameter block
  5577.   ¨  16  ioResult  word  result code 
  5578.   Æ  26  csCode  word  always EWrite
  5579.   Æ  30  EPointer  pointer  pointer to write-data structure
  5580.  
  5581. The EWrite function uses the .ENET driver to send a data packet over Ethernet.
  5582. You must first prepare a write-data structure, which specifies the destination
  5583. address and the protocol type and contains the data that you want to send. You
  5584. place a pointer to the write-data structure in the EPointer parameter. If you
  5585. want to send a packet larger than 768 bytes, you must first call the ESetGeneral
  5586. command to put the .ENET driver in general transmission mode. If the size of the
  5587. packet you provide is less than 60 bytes, the driver adds pad bytes to the
  5588. packet. Write-data structures are described in “Using a Write-Data Structure to
  5589. Transmit Ethernet Data” earlier in this chapter.
  5590.  
  5591. The ioResult parameter returns the result of the function; if you call the
  5592. function asynchronously, the function sets this field to 1 as soon as it begins
  5593. execution, and changes the field to the actual result code when it completes
  5594. execution. The csCode parameter is a routine selector that is set automatically
  5595. for you by the MPW interface; it is always equal to EWrite for this function.
  5596.  
  5597. Result codes
  5598. noErr            0  no error
  5599. elenErr             packet too large or first write-data-structure entry did
  5600.                     not contain the full 14-byte header
  5601. excessCollsns  –95  hardware error
  5602.  
  5603. FUNCTION ERead (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5604.  
  5605. Parameter block
  5606.   ¨  16  ioResult  word  result code 
  5607.   Æ  26  csCode  word  always ERead
  5608.   Æ  28  EProtType  word  Ethernet protocol type
  5609.   Æ  30  EPointer  pointer  pointer to data buffer
  5610.   Æ  34  EBuffSize  word  size of data buffer
  5611.   ¨  36  EDataSize  word  number of bytes read
  5612.  
  5613. The ERead function uses the default protocol handler to read a data packet and
  5614. place it in a data buffer. You can use the ERead function to read packets of a
  5615. particular protocol type only after you have used the EAttachPH function to
  5616. specify a NIL pointer to the protocol handler for that protocol type.
  5617.  
  5618. The ioResult parameter returns the result of the function; if you call the
  5619. function asynchronously, the function sets this field to 1 as soon as it begins
  5620. execution, and changes the field to the actual result code when it completes
  5621. execution. The csCode parameter is the routine selector, automatically set by
  5622. the MPW interface. It is always ERead for this function. The ccbRefNum parameter
  5623. is the connection control block reference number that was returned by the
  5624. dspInit command. 
  5625.  
  5626. The EProtType parameter specifies the protocol type of the packet you want to
  5627. read. The EPointer parameter is a pointer to the data buffer into which you want
  5628. to read data, and the EBuffSize parameter indicates the size of the data buffer.
  5629. If you are expecting EtherTalk data packets, the buffer should be at least 617
  5630. bytes in size; if you are expecting general Ethernet data packets, the buffer
  5631. should be at least 1514 bytes in size. 
  5632.  
  5633. The ERead function places the entire packet—including the packet header—into
  5634. your buffer. The function returns in the EDataSize parameter the number of bytes
  5635. actually read. If the packet is larger than the data buffer, the ERead function
  5636. places as much of the packet as will fit into the buffer and returns the
  5637. buf2SmallErr result code.
  5638.  
  5639. Call the ERead function asynchronously to await the next data packet. When the
  5640. .ENET driver receives the data packet, it completes execution of the ERead
  5641. function and calls your completion routine. If the .ENET driver receives a data
  5642. packet with a protocol type for which you specified the default protocol
  5643. handler, but there is no ERead command pending, the driver discards the data
  5644. packet.
  5645.  
  5646. You can have several asynchronous calls to the ERead function pending execution
  5647. simultaneously, as long as you use a different parameter block for each call.
  5648.  
  5649. Result codes
  5650. noErr             0  no error
  5651. LAPProtErr      –94  protocol not attached or protocol handler pointer was not 0
  5652. buf2SmallErr  –3101  packet too large for buffer; partial data returned
  5653. reqAborted    –1105  ERdCancel function called for this ERead
  5654.  
  5655. FUNCTION ERdCancel (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5656.  
  5657. Parameter block
  5658.   ¨  16  ioResult  word  result code 
  5659.   Æ  26  csCode  word  always ERdCancel
  5660.   Æ  30  EPointer  pointer  pointer to ERead parameter block
  5661.  
  5662. The ERdCancel function cancels execution of a specific call to the ERead
  5663. function. You must have called the ERead function asynchronously to use the
  5664. ERdCancel function. You specify in the EPointer parameter a pointer to the
  5665. parameter block that you used when you called the ERead function. 
  5666. The ioResult parameter returns the result of the function; if you call the
  5667. function asynchronously, the function sets this field to 1 as soon as it begins
  5668. execution, and changes the field to the actual result code when it completes
  5669. execution. The csCode parameter is the routine selector, automatically set by
  5670. the MPW interface. It is always ERdCancel for this function. The ccbRefNum
  5671. parameter is the connection control block reference number that was returned by
  5672. the dspInit command. 
  5673.  
  5674. Result codes
  5675. noErr           0  no error
  5676. CBNotFound  –1102  ERead not active
  5677.  
  5678. FUNCTION EGetInfo (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5679.  
  5680. Parameter block
  5681.   ¨  16  ioResult  word  result code 
  5682.   Æ  26  csCode  word  always EGetInfo
  5683.   Æ  30  EPointer  pointer  pointer to buffer
  5684.   Æ  34  EBuffSize  word  size of buffer
  5685.  
  5686. The EGetInfo function returns information about the .ENET driver. Before calling
  5687. this function, you must allocate a data buffer of at least 18 bytes. Put a
  5688. pointer to the buffer in the EPointer parameter and the size of the buffer in
  5689. the EBuffSize parameter.
  5690.  
  5691. The EGetInfo function places the following information in the data buffer:
  5692.  
  5693. Bytes  Information
  5694.  
  5695. 1–6    Ethernet address of the node on which the driver is installed
  5696. 7–10   Number of times the receive buffer has overflowed
  5697. 11–14  Number of data transmission operations that have timed out 
  5698. 15–18  Number of packets received that contain an incorrect address
  5699.  
  5700. The ioResult parameter returns the result of the function; if you call the
  5701. function asynchronously, the function sets this field to 1 as soon as it begins
  5702. execution, and changes the field to the actual result code when it completes
  5703. execution. The csCode parameter is the routine selector, automatically set by
  5704. the MPW interface. It is always EGetInfo for this function. The ccbRefNum
  5705. parameter is the connection control block reference number that was returned by
  5706. the dspInit command. 
  5707.  
  5708. Result code
  5709. noErr  0  no error
  5710.  
  5711. FUNCTION ESetGeneral (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5712.  
  5713. Parameter block
  5714.   ¨  16  ioResult  word  result code 
  5715.   Æ  26  csCode  word  always ESetGeneral
  5716.  
  5717. The ESetGeneral function switches the .ENET driver from limited-transmission
  5718. mode to general-transmission mode. In limited-transmission mode, the .ENET
  5719. driver allocates a write-data buffer of 768 bytes. This buffer size is more than
  5720. sufficient to hold an EtherTalk data packet, which can be no larger than 617
  5721. bytes. In general-transmission mode, the .ENET driver can transmit an Ethernet
  5722. data packet of up to 1514 bytes.
  5723.  
  5724. The ioResult parameter returns the result of the function; if you call the
  5725. function asynchronously, the function sets this field to 1 as soon as it begins
  5726. execution, and changes the field to the actual result code when it completes
  5727. execution. The csCode parameter is the routine selector, automatically set by
  5728. the MPW interface. It is always ESetGeneral for this function. The ccbRefNum
  5729. parameter is the connection control block reference number that was returned by
  5730. the dspInit command. 
  5731.  
  5732. There is no command to switch the .ENET driver from general-transmission mode to
  5733. limited-transmission mode. To switch back to limited-transmission mode, you have
  5734. to reset the driver by restarting the computer.
  5735.  
  5736. Result codes
  5737. noErr  0  no error
  5738. _______________________________________________________________________________
  5739.  
  5740. æKY Adding…and…Removing…Ethernet…Multicast…Addresses
  5741. æC »Adding and Removing Ethernet Multicast Addresses                     AppleTalk Manager
  5742. _______________________________________________________________________________
  5743.  
  5744. FUNCTION EAddMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5745.  
  5746. Parameter block
  5747.   ¨  16  ioResult  word  result code 
  5748.   Æ  26  csCode  word  always EAddMulti
  5749.   Æ  28  EMultiAddr  6 bytes  multicast address
  5750.  
  5751. The EAddMulti function adds a multicast address to the node on which the .ENET
  5752. driver is running. A multicast address is an Ethernet address for which the node
  5753. accepts packets just as it does to its permanently assigned Ethernet hardware
  5754. address. In a muticast address, the low-order bit of the high-order byte is set
  5755. to 1. Each node can have any number of multicast addresses, and any number of
  5756. nodes can have the same multicast address. The purpose of a multicast address is
  5757. to allow a group of Ethernet nodes to receive the same transmission
  5758. simultaneously, in a fashion similar to the AppleTalk broadcast service.
  5759.  
  5760. You must provide (in the EMultiAddr parameter) the multicast address that you
  5761. want to use. Each time a client of the .ENET driver calls the EAddMulti function
  5762. for a particular multicast address, the driver increments a counter for that
  5763. multicast address. Each time a client of the .ENET driver calls the EDelMulti
  5764. function, the driver decrements the counter for that address. As long as the
  5765. count for a multicast address is equal to or greater than 1, the .ENET driver
  5766. accepts packets directed to that multicast address. If any client of the .ENET
  5767. driver in the node has called the EAddMulti function for a particular multicast
  5768. address, therefore, the driver receives packets delivered to that address.
  5769.  
  5770. The ioResult parameter returns the result of the function; if you call the
  5771. function asynchronously, the function sets this field to 1 as soon as it begins
  5772. execution, and changes the field to the actual result code when it completes
  5773. execution. The csCode parameter is the routine selector, automatically set by
  5774. the MPW interface. It is always EAddMulti for this function. The ccbRefNum
  5775. parameter is the connection control block reference number that was returned by
  5776. the dspInit command. 
  5777.  
  5778. Result codes
  5779. noErr        0  no error
  5780. eMultiErr    invalid address or table is full 
  5781.  
  5782. FUNCTION EDelMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  5783.  
  5784. Parameter block
  5785.   ¨  16  ioResult  word  result code 
  5786.   Æ  26  csCode  word  always EDelMulti
  5787.   Æ  28  EMultiAddr  6 bytes  multicast address
  5788.  
  5789. The EDelMulti function decrements the counter kept by the .ENET driver for a
  5790. particular multicast address. Each time a client of the .ENET driver calls the
  5791. EAddMulti function, the driver increments a counter for the multicast address
  5792. specified by the EMultiAddr parameter. Each time a client of the .ENET driver
  5793. calls the EDelMulti function, the driver decrements the counter for the address
  5794. specified by the EMultiAddr parameter. As long as the count for a multicast
  5795. address is equal to or greater than 1, the .ENET driver accepts packets directed
  5796. to that multicast address. When the count for an address equals 0, the driver
  5797. removes that address from the list of multicast addresses that it accepts.
  5798.  
  5799. Note:  Because more than one client of the .ENET driver might be using a
  5800. particular multicast address, you should call the EDelMulti function only once
  5801. for each time you called the EAddMulti function.
  5802.  
  5803. The ioResult parameter returns the result of the function; if you call the
  5804. function asynchronously, the function sets this field to 1 as soon as it begins
  5805. execution, and changes the field to the actual result code when it completes
  5806. execution. The csCode parameter is the routine selector, automatically set by
  5807. the MPW interface. It is always EDelMulti for this function. The ccbRefNum
  5808. parameter is the connection control block reference number that was returned by
  5809. the dspInit command. 
  5810.  
  5811. Result codes
  5812. noErr      0  no error
  5813. eMultiErr     address not found
  5814. _______________________________________________________________________________
  5815.  
  5816. æKY Summary…of…the…AppleTalk…Manager
  5817. æC »SUMMARY OF THE APPLETALK MANAGER                                     AppleTalk Manager
  5818. _______________________________________________________________________________
  5819.  
  5820. The following cards summarize the constants, data types, and routines for the
  5821. AppleTalk Manager.
  5822. _______________________________________________________________________________
  5823.  
  5824. æKY AppleTalk…Constants
  5825. æC »Constants                                                            AppleTalk Manager
  5826. _______________________________________________________________________________
  5827.  
  5828. CONST
  5829. {csCodes for new .XPP driver routines}
  5830.   xCall = 246;
  5831.  
  5832. {xppSubCodes}
  5833.   getLocalZones = 5;
  5834.   getZoneList   = 6;
  5835.   getMyZone     = 7;
  5836.  
  5837.  
  5838. {driver control csCodes}
  5839. dspInit       = 255;  {create a new connection end}
  5840. dspRemove     = 254;  {remove a connection end}
  5841. dspOpen       = 253;  {open a connection}
  5842. dspClose      = 252;  {close a connection}
  5843. dspCLInit     = 251;  {create a connection listener}
  5844. dspCLRemove   = 250;  {remove a connection listener}
  5845. dspCLListen   = 249;  {post a listener request}
  5846. dspCLDeny     = 248;  {deny an open connection request}
  5847. dspStatus     = 247;  {get status of connection end}
  5848. dspRead       = 246;  {read data from the connection}
  5849. dspWrite      = 245;  {write data on the connection}
  5850. dspAttention  = 244;  {send an attention message}
  5851. dspOptions    = 243;  {set connection end options}
  5852. dspReset      = 242;  {forward reset the connection}
  5853. dspNewCID     = 241;  {generate a cid for a connection end}
  5854.  
  5855. {connection opening modes}
  5856. ocRequest    = 1;  {request a connection with remote}
  5857. ocPassive    = 2;  {wait for a connection request from remote}
  5858. ocAccept     = 3;  {accept request as delivered by listener}
  5859. ocEstablish  = 4;  {consider connection to be open}
  5860.  
  5861. {connection end states}
  5862. sListening  = 1;  {for connection listeners}
  5863. sPassive    = 2;  {waiting for a connection request from remote}
  5864. sOpening    = 3;  {requesting a connection with remote}
  5865. sOpen       = 4;  {connection is open}
  5866. sClosing    = 5;  {connection is being torn down}
  5867. sClosed     = 6;  {connection end state is closed}
  5868.  
  5869. {client event flags}
  5870. eClosed     = $80;  {received connection closed advice}
  5871. eTearDown   = $40;  {closed due to broken connection}
  5872. eAttention  = $20;  {received attention message}
  5873. eFwdReset   = $10;  {received forward reset advice}
  5874.  
  5875. {miscellaneous constants}
  5876. attnBufSize      = 570;  {size of client attention buffer}
  5877. minDSPQueueSize  = 100;  {Minimum size of receive or send Queue}
  5878. _______________________________________________________________________________
  5879.  
  5880. æKY AppleTalk…Data…Types
  5881. æC »Data Types                                                           AppleTalk Manager
  5882. _______________________________________________________________________________
  5883.  
  5884. TYPE ATQentry = RECORD
  5885.    qLink:     ATQentryPtr;  {next queue entry}
  5886.    qType:     INTEGER;      {unused}
  5887.    CallAddr:  ProcPtr       {pointer to your routine}
  5888. END;
  5889.  
  5890. ATQentryptr = ^ATQentry;
  5891.  
  5892. TPCCB = ^TRCCB;
  5893.  
  5894. TRCCB = PACKED RECORD
  5895.    ccbLink:        TPCCB;      {link to next CCB}
  5896.    refNum:         INTEGER;    {user reference number}
  5897.    state:          INTEGER;    {state of the connection end}
  5898.    userFlags:      Byte;       {user flags for connection}
  5899.    localSocket:    Byte;       {local socket number}
  5900.    remoteAddress:  AddrBlock;  {remote end internet address}
  5901.    attnCode:       INTEGER;    {attention code received}
  5902.    attnSize:       INTEGER;    {size of attention data}
  5903.    attnPtr:        Ptr;        {pointer to attention data}
  5904.    reserved:       PACKED ARRAY [1..220] OF Byte {reserved for use by ADSP}
  5905. END;
  5906.  
  5907. AddrBlock = PACKED RECORD
  5908.   aNet:     INTEGER;  {network number}
  5909.   aNode:    Byte;     {node ID}
  5910.   aSocket:  Byte      {socket number}
  5911. END;
  5912.  
  5913. DSPParamBlock = PACKED RECORD
  5914.   qLink:          QElemPtr;   {next queue entry}
  5915.   qType:          INTEGER;    {queue type}
  5916.   ioTrap:         INTEGER;    {routine trap}
  5917.   ioCmdAddr:      Ptr;        {routine address}
  5918.   ioCompletion:   ProcPtr;    {completion routine}
  5919.   ioResult:       OSErr;      {result code}
  5920.   ioNamePtr:      StringPtr;  {used only for Open routine}
  5921.   ioVRefNum:      INTEGER;    {volume reference number}
  5922.   ioCRefNum:      INTEGER;    {driver reference number}
  5923.   csCode:         INTEGER;    {primary command code}
  5924.   qStatus:        LONGINT;    {reserved for ADSP}
  5925.   ccbRefNum:      INTEGER;    {CCB reference number}
  5926.   CASE INTEGER OF
  5927.    dspInit,
  5928.    dspCLInit:
  5929.    (
  5930.     ccbPtr:       TPCCB;      {pointer to CCB}
  5931.     userRoutine:  ProcPtr;    {pointer to user routine}
  5932.     sendQSize:    INTEGER;    {size of send queue}
  5933.     sendQueue:    Ptr;        {pointer to send queue}
  5934.     recvQSize:    INTEGER;    {size of receive queue}
  5935.     recvQueue:    Ptr;        {pointer to receive queue}
  5936.     attnPtr:      Ptr;        {pointer to attention-message buffer}
  5937.     localSocket:  Byte;       {local socket number}
  5938.    ); 
  5939.  
  5940.   dspOpen,
  5941.   dspCLListen,
  5942.   dspCLDeny:
  5943.    (
  5944.     localCID:       INTEGER;    {local connection ID}
  5945.     remoteCID:      INTEGER;    {remote connection ID}
  5946.     remoteAddress:  AddrBlock;  {remote internet address}
  5947.     filterAddress:  AddrBlock;  {address filter}
  5948.     sendSeq:        LONGINT;    {send sequence number}
  5949.     sendWindow:     INTEGER;    {size of remote buffer}
  5950.     recvSeq:       LONGINT;   {receive sequence number}
  5951.    attnSendSeq:   LONGINT;   {attention send seq number}
  5952.    attnRecvSeq:   LONGINT;   {attention receive seq num}
  5953.    ocMode:        Byte;      {connection opening mode}
  5954.     ocInterval:     Byte;       {interval bet open requests}
  5955.     ocMaximum:      Byte;       {retries of open conn req}
  5956.    );
  5957.  
  5958. dspClose,
  5959. dspRemove:
  5960. (
  5961.   abort:            Byte;       {abort send requests}
  5962. );
  5963.  
  5964. dspStatus:
  5965. (
  5966.   statusCCB:        TPCCB;      {pointer to CCB}
  5967.   sendQPending:     INTEGER;    {bytes waiting in send queue}
  5968.   sendQFree:        INTEGER;    {available send-queue buffer}
  5969.   recvQPending:     INTEGER;    {bytes in receive queue}
  5970.   recvQFree:        INTEGER;    {avail receive-queue buffer}
  5971. )
  5972.  
  5973. dspRead,
  5974. dspWrite:
  5975. (
  5976.   reqCount:  INTEGER;  {requested number of bytes}
  5977.   actCount:  INTEGER;  {actual number of bytes}
  5978.   dataPtr:   Ptr;      {pointer to data buffer}
  5979.   eom:       Byte;     {1 if end of message}
  5980.   flush:     Byte;     {1 to send data now}
  5981. )
  5982.  
  5983. dspAttention:
  5984. (
  5985.   attnCode:      INTEGER;  {client attention code}
  5986.   attnSize:      INTEGER;  {size of attention data}
  5987.   attnData:      Ptr;   {pointer to attention data}
  5988.   attnInterval:  Byte;  {reserved}
  5989. )
  5990.  
  5991. dspOptions:
  5992. (
  5993.   sendBlocking:  INTEGER;  {send-blocking threshold}
  5994.   sendTimer:      Byte;    {reserved}
  5995.   rtmtTimer:      Byte;    {reserved}
  5996.   badSeqMax:      Byte;    {retransmit advice threshold}
  5997.   useCheckSum:    Byte;    {DDP checksum for packets}
  5998. )
  5999.  
  6000. dspNewCID:
  6001. (
  6002.   newCID:  INTEGER;  {new connection ID}
  6003. )
  6004. END;
  6005.  
  6006. xCallParam = PACKED RECORD
  6007. qLink:   QElemPtr;  {next queue entry}
  6008. qType:       INTEGER;    {queue type}
  6009. ioTrap:       INTEGER;   {routine trap}
  6010. ioCmdAddr:    Ptr;       {routine address}
  6011. ioCompletion: ProcPtr;   {completion routine}
  6012. ioResult:     OsErr;     {result code}
  6013. ioNamePtr:    StringPtr; {used only for Open routine}
  6014. ioVRefNum:    INTEGER;   {volume reference number}
  6015. ioRefNum:     INTEGER;   {driver reference number}
  6016. csCode:       INTEGER;   {primary command code}
  6017. xppSubCode:   INTEGER;   {secondary command code}
  6018. xppTimeOut:   Byte;      {timeout period for .XPP}
  6019. xppRetry:     Byte;      {retry count}
  6020. filler:       INTEGER;   {reserved}
  6021. zipBuffPtr:   Ptr;       {returned zone names}
  6022. zipNumZones:  INTEGER;   {number of zones returned}
  6023. zipLastFlag:  Byte;      {nonzero when all zone names have been returned}
  6024. filler:       Byte;      {reserved}
  6025. zipInfoField: packed array[1..70] of Byte
  6026.       {reserved for use by .XPP}
  6027. END;
  6028.  
  6029. XCallParamPtr = ^XCallParam;
  6030. EParamBlock = PACKED RECORD
  6031. qLink:   QElemPtr;  {next queue entry}
  6032. qType:   INTEGER;  {queue type}
  6033. ioTrap:   INTEGER;  {routine trap}
  6034. ioCmdAddr:   Ptr;  {routine address}
  6035. ioCompletion:   ProcPtr;  {completion routine}
  6036. ioResult:   OsErr;  {result code}
  6037. ioNamePtr:   StringPtr;  {driver name}
  6038. ioVRefNum:   INTEGER;  {volume reference number}
  6039. ioCRefNum:   INTEGER;  {driver reference number}
  6040. csCode:   INTEGER;  {primary command code}
  6041.  
  6042. CASE INTEGER OF
  6043. EWrite,
  6044. EAttachPH,
  6045. EDetachPH,
  6046. ERead,
  6047. ERdCancel,
  6048. EGetInfo,
  6049. ESetGeneral:
  6050.  
  6051. (
  6052. EProtType:  INTEGER;  {Ethernet protocol type}
  6053. EPointer:  Ptr;  {pointer; use depends on }
  6054.       { function}
  6055. EBuffSize  INTEGER  {buffer size}
  6056. EDataSize  INTEGER  {number of bytes read}
  6057. );
  6058.  
  6059. EAddMulti,
  6060. EDelMulti:
  6061.  
  6062. (
  6063. EMultiAddr:  ?????;  {Multicast address}
  6064. );
  6065. END;
  6066. _______________________________________________________________________________
  6067.  
  6068. æKY AppleTalk…Routines
  6069. æC »Routines                                                             AppleTalk Manager
  6070. _______________________________________________________________________________
  6071.  
  6072. Getting Information About the .MPP Driver
  6073.  
  6074. FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  6075.  
  6076. Parameter block
  6077.   ¨  16  ioResult  word  result code 
  6078.   Æ  26  csCode  word  always PGetAppleTalkInfo
  6079.   Æ  28  version  word  version of function
  6080.   ¨  30  varsPtr  pointer  pointer to MPP globals
  6081.   ¨  34  dcePtr  pointer  pointer to DCE for .MPP
  6082.   ¨  38  portID  word  port number 
  6083.   ¨  40  configuration  long  configuration flags
  6084.   ¨  44  selfSend  word  nonzero if self-send is enabled
  6085.   ¨  46  netLo  word  low value of the network range
  6086.   ¨  48  netHi  word  high value of the network range
  6087.   ¨  50  ourAddr  long  local 24-bit AppleTalk address
  6088.   ¨  54  routerAddr  long  24-bit address of router
  6089.   ¨  58  numOfPHs  word  max number of protocol handlers
  6090.   ¨  60  numOfSkts  word  max number of static sockets
  6091.   ¨  62  numNBPEs  word  max concurrent NBP requests
  6092.   ¨  64  ntQueue  pointer  pointer to registered name queue
  6093.   ´  68  laLength  word  length in bytes of data link address
  6094.           (extended networks only)
  6095.   Æ  70  linkAddr  pointer  pointer to data link address buffer
  6096.           (extended networks only)
  6097.   Æ  74  zoneName  pointer  pointer to zone name buffer
  6098.  
  6099. Adding and Removing AppleTalk Transition Queue Entries
  6100.  
  6101. PROCEDURE LAPAddATQ (entryPtr: pointer);
  6102. PROCEDURE LAPRmvATQ (entryPtr: pointer);
  6103. PROCEDURE LAPGetATQ (VAR eqPtr: pointer);
  6104.  
  6105. Sending Messages to the AppleTalk Transition Queue
  6106.  
  6107. FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  6108.  
  6109. Parameter block
  6110.   Æ  26  csCode  word  always PATalkClosePrep
  6111.   Æ      appName  pointer  buffer for name of application that 
  6112.           denies request
  6113.  
  6114. FUNCTION PCancelATClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  6115.  
  6116. Parameter block
  6117.   Æ  26  csCode  word  always PCancelATClosePrep 
  6118.  
  6119. Attaching and Detaching 802.2 Protocol Handlers
  6120.  
  6121. FUNCTION L802Attach (Eref: word; handlerPtr: procptr; 
  6122.            ProtType: pointer) : OSErr;
  6123. FUNCTION L802Detach (Eref: word; ProtType: pointer) : OSErr;
  6124.  
  6125. Canceling Asynchronous Calls to the ATPKillAllGetReq Function 
  6126.  
  6127. FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  6128.  
  6129. Parameter block
  6130.   Æ  26  csCode  word  always ATPKillAllGetReq
  6131.   Æ  28  atpSocket  byte  socket for which to cancel all calls 
  6132.           to ATPGetRequest
  6133.  
  6134. Using the .XPP Driver to Obtain Zone Information
  6135.  
  6136. FUNCTION GetMyZone (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  6137.  
  6138. Parameter block
  6139.   ¨  16  ioResult  word  result code 
  6140.   Æ  26  csCode  word  routine selector; always xCall
  6141.   Æ  28  xppSubCode  word  routine selector; getMyZone
  6142.   Æ  30  xppTimeOut  byte  retry interval in seconds
  6143.   Æ  31  xppRetry  byte  retry count
  6144.   Æ  34  zipBuffPtr  long  pointer to data buffer
  6145.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  6146.  
  6147. FUNCTION GetLocalZones (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  6148.  
  6149. Parameter block
  6150.   ¨  16  ioResult  word  result code 
  6151.   Æ  26  csCode  word  routine selector; always xCall
  6152.   Æ  28  xppSubCode  word  routine selector; getLocalZones
  6153.   Æ  30  xppTimeOut  byte  retry interval in seconds
  6154.   Æ  31  xppRetry  byte  retry count
  6155.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  6156.   ¨  38  zipNumZones  word  number of names returned
  6157.   ¨  40  zipLastFlag  byte  nonzero if no more names
  6158.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  6159.  
  6160. FUNCTION GetZoneList (thePBptr:XCallParamPtr; async: BOOLEAN) : OSErr;
  6161.  
  6162. Parameter block
  6163.   ¨  16  ioResult  word  result code 
  6164.   Æ  26  csCode  word  routine selector; always xCall
  6165.   Æ  28  xppSubCode  word  routine selector; getZoneList
  6166.   Æ  30  xppTimeOut  byte  retry interval in seconds
  6167.   Æ  31  xppRetry  byte  retry count
  6168.   Æ  34  zipBuffPtr  pointer  pointer to data buffer
  6169.   ¨  38  zipNumZones  word  number of names returned
  6170.   ¨  40  zipLastFlag  byte  nonzero if no more names
  6171.   Æ  42  zipInfoField  70 bytes  for use by ZIP; first word set to 0
  6172.  
  6173. Attaching and Detaching an Ethernet Protocol Handler
  6174.  
  6175. FUNCTION EAttachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6176.  
  6177. Parameter block
  6178.   ¨  16  ioResult  word  result code 
  6179.   Æ  26  csCode  word  always EAttachPH
  6180.   Æ  28  EProtType  word  Ethernet protocol type
  6181.   Æ  30  EPointer  pointer  pointer to protocol handler
  6182.  
  6183. FUNCTION EDetachPH (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6184.  
  6185. Parameter block
  6186.   ¨  16  ioResult  word  result code 
  6187.   Æ  26  csCode  word  always EDetachPH
  6188.   Æ  28  EProtType  word  Ethernet protocol type
  6189.  
  6190. Writing and Reading Ethernet Packets Using the Default Protocol Handler
  6191.  
  6192. FUNCTION EWrite (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6193.  
  6194. Parameter block
  6195.   ¨  16  ioResult  word  result code 
  6196.   Æ  26  csCode  word  always EWrite
  6197.   Æ  30  EPointer  pointer  pointer to write-data structure
  6198.  
  6199. FUNCTION ERead (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6200.  
  6201. Parameter block
  6202.   ¨  16  ioResult  word  result code 
  6203.   Æ  26  csCode  word  always ERead
  6204.   Æ  28  EProtType  word  Ethernet protocol type
  6205.   Æ  30  EPointer  pointer  pointer to data buffer
  6206.   Æ  34  EBuffSize  word  size of data buffer
  6207.   ¨  36  EDataSize  word  number of bytes read
  6208.  
  6209. FUNCTION ERdCancel (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6210.  
  6211. Parameter block
  6212.   ¨  16  ioResult  word  result code 
  6213.   Æ  26  csCode  word  always ERdCancel
  6214.   Æ  30  EPointer  pointer  pointer to ERead parameter block
  6215.  
  6216. FUNCTION EGetInfo (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6217.  
  6218. Parameter block
  6219.   ¨  16  ioResult  word  result code 
  6220.   Æ  26  csCode  word  always EGetInfo
  6221.   Æ  30  EPointer  pointer  pointer to buffer
  6222.   Æ  34  EBuffSize  word  size of buffer
  6223.  
  6224. FUNCTION ESetGeneral (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6225.  
  6226. Parameter block
  6227.   ¨  16  ioResult  word  result code 
  6228.   Æ  26  csCode  word  always ESetGeneral
  6229.  
  6230. Adding and Removing Ethernet Multicast Addresses
  6231.  
  6232. FUNCTION EAddMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6233.  
  6234. Parameter block
  6235.   ¨  16  ioResult  word  result code 
  6236.   Æ  26  csCode  word  always EAddMulti
  6237.   Æ  28  EMultiAddr  6 bytes  multicast address
  6238.  
  6239. FUNCTION EDelMulti (thePBptr: EPBPtr; async: BOOLEAN) : OSErr;
  6240.  
  6241. Parameter block
  6242.   ¨  16  ioResult  word  result code 
  6243.   Æ  26  csCode  word  always EDelMulti
  6244.   Æ  28  EMultiAddr  6 bytes  multicast address
  6245. _______________________________________________________________________________
  6246.  
  6247. æKY AppleTalk…Result…codes
  6248. æC »Result codes                                                         AppleTalk Manager
  6249. _______________________________________________________________________________
  6250.  
  6251. eMultiErr                invalid address or table is full 
  6252. elenErr                  packet too large or first write-data-structure entry
  6253.                          did not contain the full 14-byte header
  6254. noErr                 0  no error
  6255. closeErr            –24  permission to close .MPP driver was denied
  6256. ddpSktErr           –91  error opening socket
  6257. noBridgeErr         –93  no router is available
  6258. LAPProtErr          –94  protocol handler is already attached or node’s protocol
  6259.  
  6260.                          table is full
  6261. LAPProtErr          –94  no protocol handler attached
  6262. LAPProtErr          –94  protocol not attached or protocol handler pointer was
  6263.                          not 0
  6264. excessCollsns       –95  hardware error
  6265. reqFailed         –1096  request to contact router failed; retry count exceeded 
  6266. cbNotFound        –1102  control block not found; no pending asynchronous calls
  6267. CBNotFound        –1102  ERead not active
  6268. reqAborted        –1105  ERdCancel function called for this ERead
  6269. errDSPQueueSize   –1274  send or receive queue is too small
  6270. errFwdReset       –1275  read terminated by forward reset
  6271. errAttention      –1276  attention message too long
  6272. errOpening        –1277  attempt to open connection failed
  6273. errState          –1278  bad connection state for this operation
  6274. errAborted        –1279  request aborted by dspRemove or dspClose command
  6275. errRefNum         –1280  bad connection reference number
  6276. buf2SmallErr      –3101  packet too large for buffer; partial data returned
  6277. _______________________________________________________________________________
  6278.  
  6279. æKY Assembly-language…Information…for…AppleTalk
  6280. æC »Assembly-language Information                                        AppleTalk Manager
  6281. _______________________________________________________________________________
  6282.  
  6283. Constants
  6284.  
  6285. mainVersion   EQU  1
  6286. subVersion    EQU  1
  6287. ;client control codes
  6288. dspInit       EQU  255  ;create a new connection end
  6289. dspRemove     EQU  254  ;remove a connection end
  6290. dspOpen       EQU  253  ;open a connection
  6291. dspClose      EQU  252  ;close a connection
  6292. dspCLInit     EQU  251  ;create a connection listener
  6293. dspCLRemove   EQU  250  ;remove a connection listener
  6294. dspCLListen   EQU  249  ;post a listener request
  6295. dspCLDeny     EQU  248  ;deny an open connection request
  6296. dspStatus     EQU  247  ;get status of connection end
  6297. dspRead       EQU  246  ;read data from the connection
  6298. dspWrite      EQU  245  ;write data on the connection
  6299. dspAttention  EQU  244  ;send an attention message
  6300. dspOptions    EQU  243  ;set connection end options
  6301. dspReset      EQU  242  ;forward reset the connection
  6302. dspNewCID     EQU  241  ;generate a cid for a connection end
  6303. ;open connection modes
  6304. ocRequest     EQU  1  ;request a connection with remote
  6305. ocPassive     EQU  2  ;wait for a connection request from remote
  6306. ocAccept      EQU  3  ;accept request as delivered by listener
  6307. ocEstablish   EQU  4  ;consider connection to be open
  6308. ;connection states
  6309. sListening    EQU  1  ;for connection listeners
  6310. sPassive      EQU  2  ;waiting for a connection request from remote
  6311. sOpening      EQU  3  ;requesting a connection with remote
  6312. sOpen         EQU  4  ;connection is open
  6313. sClosing      EQU  5  ;connection is being torn down
  6314. sClosed       EQU  6  ;connection end state is closed
  6315. ;client event flags (bit-mask)
  6316. eClosed       EQU  $80  ;received connection closed advice
  6317. eTearDown     EQU  $40  ;closed due to broken connection
  6318. eAttention    EQU  $20  ;received attention message
  6319. eFwdReset     EQU  $10  ;received forward reset advice
  6320. ;miscellaneous equates
  6321. attnBufSize      EQU  570  ;size of client attention message
  6322. minDSPQueueSize  EQU  100  ;minimum size for both receive and send queues
  6323. ;connection control block equates & size
  6324. ccbLink          EQU  0                ;link to next ccb
  6325. refNum           EQU  ccbLink+4        ;user reference number
  6326. state            EQU  refNum+2         ;state of the connection end
  6327. userFlags        EQU  state+2          ;flags for unsolicited connection events
  6328. localSocket      EQU  userFlags+1      ;socket number of this connection end
  6329. remoteAddress    EQU  localSocket+1    ;internet address of remote end
  6330. attnCode         EQU  remoteAddress+4  ;attention code received
  6331. attnSize         EQU  attnCode+2       ;size of received attention data
  6332. attnPtr          EQU  attnSize+2       ;ptr to received attention data
  6333. ccbSize          EQU  attnPtr+224      ;total byte size of ccb
  6334. ;adsp queue element equates & size
  6335. csQStatus    EQU  CSParam  ;adsp internal use
  6336. csCCBRef     EQU  csQStatus+4  ;refnum of ccb
  6337. ;dspInit, dspCLInit
  6338. csCCBPtr     EQU  csCCBRef+2     ;pointer to connection control block
  6339. csUserRtn    EQU  csCCBPtr+4     ;client routine to call on event
  6340. csSendQSize  EQU  csUserRtn+4    ;size of send queue (0..64K bytes)
  6341. csSendQueue  EQU  csSendQSize+2  ;client passed send queue buffer
  6342. csRecvQSize  EQU  csSendQueue+4  ;size of receive queue (0..64 KBb)
  6343. csRecvQueue  EQU  csRecvQSize+2  ;client passed receive queue buffer
  6344. csAttnPtr    EQU  csRecvQueue+4  ;client passed receive attention buffer
  6345. csLocSkt     EQU  csAttnPtr+4    ;local socket number
  6346. ;dspOpen, dspCLListen, dspCLDeny
  6347. csLocCID       EQU  csCCBRef+2    ;local connection id
  6348. csRemCID       EQU  csLocCID+2    ;remote connection id
  6349. csRemAddr      EQU  csRemCID+2    ;address of remote end
  6350. csFltrAddr     EQU  csRemAddr+4   ;address filter
  6351. csSendSeq      EQU  csFltrAddr+4  ;local send sequence number
  6352. csSendWdw      EQU  csSendSeq+4   ;send window size
  6353. csRecvSeq      EQU  csSendWdw+2   ;receive sequence number
  6354. csAttnSendSeq  EQU  csRecvSeq+4   ;attention send sequence number
  6355. csAttnRecvSeq  EQU  csAttnSendSeq+4  ;attention receive sequence number
  6356. csOCMode       EQU  csAttnRecvSeq+4  ;open connection mode
  6357. csOCInterval   EQU  csOCMode+1       ;open connection request retry interval
  6358. csOCMaximum    EQU  csOCInterval+1   ;open connection request retry maximum
  6359. ;dspClose, dspRemove
  6360. csAbort      EQU  csCCBRef+2     ;abort connection immediately if non-zero
  6361. ;dspStatus
  6362. csSQPending  EQU  csCCBPtr+4     ;pending bytes in send queue
  6363. csSQFree     EQU  csSQPending+2  ;available buffer space in send queue
  6364. csRQPending  EQU  csSQFree+2     ;pending bytes in receive queue
  6365. csRQFree     EQU  csRQPending+2  ;available buffer space in receive queue
  6366. ;dspRead, dspWrite
  6367. csReqCount      EQU  csCCBRef+2    ;requested number of bytes
  6368. csActCount      EQU  csReqCount+2  ;actual number of bytes
  6369. csDataPtr       EQU  csActCount+2  ;pointer to data buffer
  6370. csEOM           EQU  csDataPtr+4   ;indicates logical end of message
  6371. csFlush         EQU  csEOM+1       ;send data now dspAttention
  6372. csAttnCode      EQU  csCCBRef+2    ;client attention code
  6373. csAttnSize      EQU  csAttnCode+2  ;size of attention data
  6374. csAttnData      EQU  csAttnSize+2  ;pointer to attention data
  6375. csAttnInterval  EQU  csAttnData+4  ;retransmit timer in 10-tick intervals
  6376. ;dspOptions
  6377. csSendBlocking  EQU  csCCBRef+2        ;quantum for data packets
  6378. csSendTimer     EQU  csSendBlocking+2  ;send timer in 10-tick intervals
  6379. csRtmtTimer     EQU  csSendTimer+1     ;retransmit timer in 10-tick intervals
  6380. csBadSeqMax     EQU  csRtmtTimer+1     ;threshold for sending retransmit advice
  6381. csUseCheckSum   EQU  csBadSeqMax+1     ;use ddp packet checksum dspNewCID
  6382. csNewCID        EQU  csCCBRef+2        ;new connection id returned
  6383. dspPBSize       EQU  68                ;byte size of largest DSP param block
  6384. _______________________________________________________________________________
  6385.  
  6386.  
  6387. æKY BinaryDecimalConversion
  6388. æC 
  6389. THE BINARY-DECIMAL CONVERSION PACKAGE
  6390. _______________________________________________________________________________
  6391.  
  6392. About…The…Binary-DecimalConversion…Chapter
  6393. Binary-Decimal…Conversion…Package…Routines
  6394. Summary…of…the…Binary-Decimal…Conversion…Package
  6395. _______________________________________________________________________________
  6396.  
  6397.  
  6398.  
  6399. æKY About…The…Binary-DecimalConversion…Chapter
  6400. æC »ABOUT THIS CHAPTER                                BinaryDecimalConversion
  6401. _______________________________________________________________________________
  6402.  
  6403. This chapter describes the Binary-Decimal Conversion Package, which contains five
  6404. routines.  One converts an integer from its internal (binary) form to a string that
  6405. represents its decimal (base 10) value; the other converts a decimal string to the
  6406. corresponding integer.
  6407.  
  6408. Three new routines have been added to the Binary-Decimal Conversion Package for the
  6409. Macintosh Plus. These routines supplement the Floating-Point Arithmetic and Transcendental
  6410. Functions Packages in providing the the Standard Apple Numeric Environment (SANE) for
  6411. the Macintosh.
  6412.  
  6413. Detailed documentation for these new routines is included with the rest of the SANE
  6414. documentation in the Apple Numerics Manual—in particular, see the chapter
  6415. “Conversions” in Part I and the three chapters “Conversions”, “Numeric Scanner and
  6416. Formatter”, and “Examples” in Part III.
  6417.  
  6418. The new routines, two numeric scanners and a numeric formatter, are intended for
  6419. programmers with special needs beyond what their development language provides. For
  6420. example, developers of programming languages can use these routines to implement the
  6421. floating-point I/O routines—such as read and write for Pascal or scanf and printf for
  6422. C—that are appropriate for their particular languages. The scanners can be used for
  6423. scanning numbers embedded in text and for numbers received character by character.
  6424. The scanners differ only in that one accepts a pointer to a Pascal strings (with an
  6425. initial length byte) as input, while the other accepts a pointer to the first character
  6426. of a character stream.
  6427.  
  6428. The scanners convert ASCII string representations of numbers into SANE decimal records.
  6429. The formatter converts SANE decimal records into ASCII string representations. The
  6430. Floating-Point Arithmetic Package converts between this decimal record format and the
  6431. SANE binary data formats.
  6432.  
  6433. The three routines handle the usual number representations, like –1.234 and
  6434. 5e–7, throughout the range and precision of the extended data format. They also
  6435. handle the special NaN, infinity, and signed-zero representations specified by the
  6436. IEEE Floating-Point Standard.
  6437.  
  6438. You should already be familiar with packages in general, as described in the Package
  6439. Manager chapter.
  6440.  
  6441. _______________________________________________________________________________
  6442.  
  6443.  
  6444. æKY Binary-Decimal…Conversion…Package…Routines
  6445. æC »BINARY-DECIMAL CONVERSION PACKAGE ROUTINES        BinaryDecimalConversion
  6446. _______________________________________________________________________________
  6447.  
  6448. The Binary-Decimal Conversion Package is contained in the ROM, beginning with the
  6449. 128K ROM. The routines are register-based, so the Pascal form of each is followed by
  6450. a box containing information needed to use the routine from assembly language.
  6451.  
  6452. Assembly-language note:  The trap macro for the Binary-Decimal Conversion
  6453.                          Package is _Pack7. The routine selectors are as
  6454.                          follows:
  6455.  
  6456.                            numToString    .EQU    0
  6457.                            stringToNum    .EQU    1
  6458.  
  6459. PROCEDURE NumToString (theNum:  LONGINT; VAR theString:  Str255);
  6460.  
  6461. On entry    A0:  pointer to theString (preceded by length byte)
  6462.             D0:  theNum (long word)
  6463. On exit     A0:  pointer to theString
  6464.  
  6465. NumToString converts theNum to a string that represents its decimal value, and returns
  6466. the result in theString. If the value is negative, the string begins with a minus
  6467. sign; otherwise, the sign is omitted. Leading zeroes are suppressed, except that the
  6468. value 0 produces '0'. For example:
  6469.  
  6470.   theNum     theString
  6471.  
  6472.     12         '12'
  6473.    –23        '–23'
  6474.      0          '0'
  6475.  
  6476. PROCEDURE StringToNum (theString:  Str255; VAR theNum:  LONGINT);
  6477.  
  6478. On entry    A0:  pointer to theString (preceded by length byte)
  6479. On exit     D0:  theNum (long word)
  6480.  
  6481. Given a string representing a decimal integer, StringToNum converts it to the corresponding
  6482. integer and returns the result in theNum. The string may begin with a plus or minus
  6483. sign. For example:
  6484.  
  6485.   theString     theNum
  6486.  
  6487.     '12'          12
  6488.    '–23'         –23
  6489.     '–0'           0
  6490.    '055'          55
  6491.  
  6492. The magnitude of the integer is converted modulo 2^32, and the 32-bit result is
  6493. negated if the string begins with a minus sign; integer overflow occurs if the magnitude
  6494. is greater than 2^31–1. (Negation is done by taking the two’s complement—reversing
  6495. the state of each bit and then adding 1.) For example:
  6496.  
  6497.   theString                               theNum
  6498.  
  6499.   '2147483648' (magnitude is 2^31)      –2147483648
  6500.  '–2147483648'                          –2147483648
  6501.   '4294967295' (magnitude is 2^32–1)    –1
  6502.  '–4294967295'                           1
  6503.  
  6504. StringToNum doesn’t actually check whether the characters in the string are between
  6505. '0' and '9'; instead, since the ASCII codes for '0' through '9' are $30 through $39,
  6506. it just masks off the last four bits and uses them as a digit. For example, '2:' is
  6507. converted to the number 30 because the ASCII code for ':' is $3A. Spaces are treated
  6508. as zeroes, since the ASCII code for a space is $20. Given that the ASCII codes for
  6509. 'C', 'A', and 'T' are $43, $41, and $54, respectively, consider the following examples:
  6510.  
  6511.   theString     theNum
  6512.  
  6513.     'CAT'        314
  6514.    '+CAT'        314
  6515.    '–CAT'       –314
  6516.  
  6517. _______________________________________________________________________________
  6518.  
  6519.  
  6520. æKY Summary…of…the…Binary-Decimal…Conversion…Package
  6521. æC »SUMMARY OF THE BINARY-DECIMAL CONVERSION PACKAGE  BinaryDecimalConversion
  6522. _______________________________________________________________________________
  6523.  
  6524. Routines
  6525.  
  6526. PROCEDURE NumToString (theNum:  LONGINT; VAR theString:  Str255);
  6527. PROCEDURE StringToNum (theString:  Str255; VAR theNum:  LONGINT);
  6528.  
  6529. _______________________________________________________________________________
  6530.  
  6531. Assembly-Language Information
  6532.  
  6533. Constants
  6534.  
  6535. ; Routine selectors
  6536.  
  6537. numToString  .EQU  0
  6538. stringToNum  .EQU  1
  6539.  
  6540. Routines
  6541.  
  6542. Name           On entry                          On exit
  6543.  
  6544. NumToString    A0:  ptr to theString             A0:  ptr to theString
  6545.                     (preceded by length byte)
  6546.                D0:  theNum (long)
  6547. StringToNum    A0:  ptr to theString             D0:  theNum (long)
  6548.                     (preceded by length byte)
  6549.  
  6550. Trap Macro Name
  6551.  
  6552. _Pack7
  6553.  
  6554.  
  6555. æKY ColorManager
  6556. æC 
  6557. THE COLOR MANAGER                                                  
  6558. _______________________________________________________________________________
  6559.  
  6560. About…The…ColorManager…Chapter
  6561. About…the…Color…Manager
  6562. Using…the…Color…Manager
  6563. Color…Manager…Routines
  6564. Custom…Search…and…Complement…Functions
  6565. Summary…of…the…Color…Manager
  6566. _______________________________________________________________________________
  6567.  
  6568.  
  6569.  
  6570. æKY About…The…ColorManager…Chapter
  6571. æC »ABOUT THIS CHAPTER                                           ColorManager
  6572. _______________________________________________________________________________
  6573.  
  6574. The Color Manager supplies color-selection support for Color QuickDraw on the Macintosh
  6575. II. The software described in this chapter allows specialized applications to fine-tune
  6576. the color-matching algorithms, and also provides utility functions that are rarely
  6577. used by applications.
  6578.  
  6579. An understanding of Color QuickDraw concepts, terminology, and data structures is
  6580. essential when using the material in this chapter. You should be familiar with RGB
  6581. color, pixel maps, pixel patterns, and other material introduced in the Color QuickDraw
  6582. chapter. You should also be familiar with the material in the Graphics Devices chapter,
  6583. since the Color Manager routines work on the device level.
  6584.  
  6585. Keep in mind that Color Manager routines are the intermediary between high-level
  6586. software such as Color QuickDraw, the Palette Manager, and the Color Picker, and the
  6587. lower-level video devices. The majority of applications will never need to use the
  6588. Color Manager routines directly.
  6589.  
  6590. Reader’s guide: The material in this chapter is largely for informational
  6591.                 purposes only, since Color QuickDraw, the Palette Manager,
  6592.                 and the other color Toolbox routines provide a detailed and
  6593.                 consistent way to add color to Macintosh programs.
  6594.  
  6595. _______________________________________________________________________________
  6596.  
  6597.  
  6598. æKY About…the…Color…Manager
  6599. æC »ABOUT THE COLOR MANAGER                                      ColorManager
  6600. _______________________________________________________________________________
  6601.  
  6602. The Color Manager is optimized to work with graphics hardware that utilizes a Color
  6603. Look-up Table (CLUT), a data structure that maps color indices, specified using
  6604. QuickDraw, into actual color values. The  exact color capabilities of the Macintosh
  6605. II depend on the particular video card used. There are three kinds of devices:
  6606.  
  6607.   •  CLUT devices contain hardware that converts an arbitrary pixel value
  6608.      stored in the frame buffer to some actual RGB video value, which is
  6609.      changeable. The pixel value could be the index to any of the colors
  6610.      in the current color set for the device, and the color set itself
  6611.      can be changed.
  6612.   •  Fixed devices also convert a pixel value to some actual RGB video
  6613.      value, but the hardware colors can’t be changed. The pixel value
  6614.      could be the index to any of the colors in the color set, but the
  6615.      color set itself always remains the same.
  6616.   •  Direct devices have a direct correlation between the value placed in
  6617.      the frame buffer and the color you see on the screen. The value placed
  6618.      in the frame buffer would produce the same color every time. Direct
  6619.      devices aren’t supported in the initial release of Color QuickDraw.
  6620.  
  6621. Applications that limit themselves to a small set of colors can use them simply and
  6622. easily from QuickDraw, with a minimum of overhead.  Color QuickDraw accesses the
  6623. Color Manager to obtain the best available color matches in the lookup table. Applications
  6624. such as color painting and animation programs, which need greater control over the
  6625. precise colors they use, can use the Palette Manager to allocate part of the color
  6626. table for their own exclusive use. The Palette Manager, described in a later chapter,
  6627. is useful for most applications that use shared color resources, imaging, or color
  6628. table animation. The Palette Manager is used whenever color is used for objects
  6629. within windows, while the Color Manager operates on the device level.
  6630.  
  6631. Note:  Palette Manager routines operate transparently across multiple
  6632.        screens, while Color Manager routines do not. Therefore, always
  6633.        use Palette Manager routines for applications that will run on
  6634.        multiple screens or in a multitasking environment.
  6635.  
  6636. The sections that follow describe how the Color Manager converts the RGB values
  6637. specified using Color QuickDraw into the actual colors available on a device. The
  6638. pixel value, specifying the number of bits per pixel, is set using the Control Panel.
  6639.  
  6640. _______________________________________________________________________________
  6641.  
  6642. »Graphics Devices
  6643.  
  6644. As with Color QuickDraw, the Color Manager accesses a particular graphics device
  6645. through a data structure known as a gDevice record. Each gDevice record stores information
  6646. about a particular graphics device; after this record is initialized, the device
  6647. itself is known to the Color Manager and QuickDraw as a gDevice. See the Graphics
  6648. Devices chapter for more details on gDevice format and on the routines that allow an
  6649. application to access a given device. Remember that a gDevice is a logical device,
  6650. which the software treats the same whether it is a video card, a display device, or
  6651. an offscreen pixel map.
  6652.  
  6653. _______________________________________________________________________________
  6654.  
  6655. »Color Table Format
  6656.  
  6657. The complete set of colors in use at a given time for a particular gDevice is summarized
  6658. in a color table record. Its format is as follows:
  6659.  
  6660. TYPE
  6661.   CTabHandle = ^CTabPtr;
  6662.   CTabPtr    = ^ColorTable;
  6663.   ColorTable = RECORD
  6664.                  ctSeed:   LONGINT;  {unique identifier from table}
  6665.                  ctFlags:  INTEGER;  {high bit is set for a gDevice, }
  6666.                                      { clear for a pixMap}
  6667.                  ctSize:   INTEGER;  {Number of entries in table-1}
  6668.                  ctTable:    cSpecArray
  6669.                END;
  6670.  
  6671. Field descriptions
  6672.  
  6673. ctSeed     The ctSeed field is similar to a version identifier number for
  6674.            a color table. If a color table is created by an application, it
  6675.            should call GetCTSeed to obtain this identifier. The ctSeed should
  6676.            be some unique number higher than minSeed, a predefined constant
  6677.            with a value of 1023. If a color table is created from a resource,
  6678.            its resource number will be used as the initial ctSeed. For 'CLUT'
  6679.            resource, the range of resource numbers should be 0–1023.
  6680.  
  6681. ctFlags    The ctFlags field is significant for gDevices only. It contains
  6682.            flags that describe the format of the ctTable. Currently, only
  6683.            the high bit is defined; all others are reserved. Color tables
  6684.            that are part of the gDevice structure always have this bit set.
  6685.            Color tables that are part of pixMaps have this bit clear. Each
  6686.            gDevice has its own pixMap, which has a color table.
  6687.  
  6688. ctSize     The ctSize field contains the number of entries in the color
  6689.            table minus one. All counts on color table entries are zero based.
  6690.  
  6691. ctTable    The ctTable field contains a cSpecArray, which is an array of
  6692.            ColorSpec entries. Notice that each entry in the color table is
  6693.            a ColorSpec, not simply an RGBColor. The type ColorSpec is
  6694.            composed of an integer value and an RGB color, as shown in the
  6695.            following specification. A color table may include a number of
  6696.            ColorSpec records.
  6697.  
  6698. TYPE
  6699.   cSpecArray = ARRAY [0..0] OF ColorSpec;
  6700.   ColorSpec  = RECORD
  6701.                  value : INTEGER;    {Color representation}
  6702.                  rgb   : RGBColor    {Color value}
  6703.                END;
  6704.   RGBColor   = RECORD
  6705.                  red   : INTEGER;    {Red component}
  6706.                  green : INTEGER;    {Green component}
  6707.                  blue  : INTEGER     {Blue component}
  6708.                END;
  6709.  
  6710. In gDevice color tables, the colorSpec.value field is reserved for use by the Color
  6711. Manager and Palette Manager. Their interpretation and values are different than the
  6712. color tables contained in pixMaps.
  6713.  
  6714. •••Refer to Figure 1.•••
  6715.  
  6716. Figure 1–Color Table Format
  6717.  
  6718. Note that the colorSpec.value field of the record is only word size (16 bits), even
  6719. though color index values (as returned by Color2Index) may be long words. The current
  6720. implementation of Color QuickDraw only supports 16 bits. The components in an RGBColor
  6721. are left-justified rather than right-justified in a word. Video drivers should respect
  6722. this convention and extract the appropriate number of bits from the high order side
  6723. of the component. For example, the Apple Graphics Card uses only the most significant
  6724. eight bits of each component of the RGBColor record.
  6725.  
  6726. _______________________________________________________________________________
  6727.  
  6728. »Inverse Tables
  6729.  
  6730. Reader’s guide: The material in this section is provided for informational
  6731.                 and debugging purposes, since most programs won’t need to
  6732.                 use inverse tables.
  6733.  
  6734. For normal drawing, Color QuickDraw takes all specifications as absolute RGB triples,
  6735. by means of the RGBColor record. Internally, these absolute specifications are converted
  6736. to the appropriate values to be written into the video card. For direct devices, the
  6737. RGB is separated into its red, green, and blue components, and each of these is
  6738. written to the video card. On CLUT and fixed devices, however, there isn’t always a
  6739. direct relationship between the specified RGB and the index value written into the
  6740. frame buffer; in fact, on CLUT devices, the best-match index value may change dynamically
  6741. as the colors available in the hardware are changed. On these types of devices, Color
  6742. QuickDraw uses the Color Manager to find the best matches among the colors currently
  6743. available.
  6744.  
  6745. The method used to determine the best available match can be specified by the application
  6746. or the system on a gDevice by gDevice basis. By default, on CLUT and fixed devices, a
  6747. special data structure called an inverse table is created. An inverse table is a
  6748. table arranged in such a manner that, given an arbitrary RGB color, the pixel value
  6749. can be very rapidly looked up.
  6750.  
  6751. In the default case, a certain number of the most significant bits of red, green, and
  6752. blue are extracted, then concatenated together to form an index into the inverse
  6753. table. At this location is the “best” match to the specified color. The number of
  6754. bits per color channel that are used to construct this index is known as the resolution
  6755. of the inverse table, and can be 3, 4, or 5 bits per channel. As the resolution of
  6756. the inverse table increases, the number of permutations of possible colors increases,
  6757. as does the size of the inverse table. Three-bit tables occupy 512 bytes, 4-bit
  6758. tables (the default) occupy 4K bytes, and 5-bit tables occupy 32K bytes.
  6759.  
  6760. A disadvantage of this method is that certain colors that are “close” together can
  6761. become hidden when they differ only in bits that weren’t used to construct the inverse
  6762. table index. For example, even if the color table were loaded with 256 levels of
  6763. gray, a 4-bit inverse table can only discriminate among 16 of the levels. To solve
  6764. this problem without having to use special-case sets of colors with hidden colors,
  6765. inverse tables carry additional information about how to find colors that differ only
  6766. in the less significant bits. As a result, when the Color2Index routine is called, it
  6767. can find the best match to the full 48-bit resolution available in a colorSpec. Since
  6768. examining the extra information takes time, certain parts of Color QuickDraw, notably
  6769. drawing in the arithmetic transfer modes, don’t use this information, and hence won’t
  6770. find the hidden colors.
  6771.  
  6772. In most cases, when setting colors using RGBForeColor and RGBBackColor, and when
  6773. using CopyBits to transfer pixMaps, inverse tables of four bits are sufficient. When
  6774. using arithmetic transfer modes with certain color tables that have closely-spaced
  6775. colors, the screen appearance may be improved by specifying inverse tables at 5-bit
  6776. resolution. Because the format of inverse tables is subject to change in the future,
  6777. or may not be present on certain devices, applications should not assume the structure
  6778. of the data.
  6779.  
  6780. The data in inverse tables remains valid as long as the color table from which it was
  6781. built remains unchanged. When a color table is modified, the inverse table must be
  6782. rebuilt, and the screen should be redrawn to take advantage of this new information.
  6783. Rather than being reconstructed when the color table is changed, the inverse table is
  6784. marked invalid, and is automatically rebuilt when next accessed.
  6785.  
  6786. Rather than testing each entry of the color table to see if it has changed, the
  6787. color-matching code compares the ctSeed of the current gDevice’s colorTable against
  6788. the iTabSeed of that gDevice’s inverse table. Each routine that modifies the colorTable
  6789. (with the exception of RestoreEntries) increments the ctSeed field of that colorTable.
  6790. If the ctSeed and the iTabSeed don’t match, the inverse table is reconstructed for
  6791. that gDevice.
  6792.  
  6793. Note:  Under normal circumstances, all invalidations are posted and serviced
  6794.        transparently to the application. This method of invalidation is the
  6795.        same as that used to invalidate expanded patterns and cursors elsewhere
  6796.        in Color QuickDraw.
  6797.  
  6798. In certain cases, it may be useful to override the inverse table matching code with
  6799. custom routines that have special matching rules. See the section titled
  6800. “Custom Search and Complement Procedures” for more details.
  6801.  
  6802. The Color Manager performs a color table look-up in the following manner:
  6803.  
  6804.   1.  Builds a table of all possible RGB values;
  6805.   2.  For each position in the table, attempts to get the closest match;
  6806.   3.  Reduces the resolution of the lookup to four bits when constructing
  6807.       the table, but later adds information to get a better resolution.
  6808.  
  6809. The Color Manager performs this table-building sequence whenever colors are requested
  6810. by Color QuickDraw, the Color Picker, or the Palette Manager. This isn’t the only
  6811. color matching method available; a custom search procedure, for example, may not have
  6812. an inverse table. (See the section titled “Custom Search and Complement Procedures”
  6813. for more information.) However, inverse tables are the default method for color
  6814. matching.
  6815.  
  6816. When using an inverse table, the table is indexed by concatenating together the
  6817. high-order bits of the three desired color components; iTabRes tells how many bits of
  6818. each component are significant. The format of an inverse table is shown below:
  6819.  
  6820. TYPE
  6821.   ITabHandle = ^ITabPtr;
  6822.   ITabPtr    = ^ITab;
  6823.   ITab       = RECORD
  6824.                  iTabSeed:  LONGINT;    {copy of color table seed}
  6825.                  iTabRes:   INTEGER;    {resolution of table}
  6826.                  iTTable:   ARRAY[0..0] OF SignedByte {byte color }
  6827.                                         { table index values}
  6828.                END;
  6829.  
  6830. The size of an index table in bytes is 2^3*iTabRes. The table below shows a sample
  6831. index table:
  6832.  
  6833. resolution        RGB color      inverse-table     size
  6834.                                  index
  6835.     4-bit         red=$1234,
  6836.                   green=$5678,
  6837.                   blue=$9ABC     $0159             2^12 = 4K bytes
  6838.  
  6839.     5-bit         red=$1234,
  6840.                   green=$5678,
  6841.                   blue=$9ABC     $0953             2^15 = 32K bytes
  6842.  
  6843. MakeITable only supports 3-bit, 4-bit, and 5-bit resolution. Five bits is the maximum
  6844. possible resolution, since the indices into a 6-bit table would have to be 18 bits
  6845. long, more than a full word.
  6846.  
  6847. _______________________________________________________________________________
  6848.  
  6849.  
  6850. æKY Using…the…Color…Manager
  6851. æC »USING THE COLOR MANAGER                                      ColorManager
  6852. _______________________________________________________________________________
  6853.  
  6854. In the simplest cases, use of the Color Manager is transparent when invoking the new
  6855. Color QuickDraw routines. Using RGBForeColor and RGBBackColor, the program requests
  6856. an RGB color for either the foreground or background. For instance, the following
  6857. code requests an RGB color of red and sets it in the cGrafPort:
  6858.  
  6859.   myColor.red:=$FFFF;
  6860.   myColor.green:=0;
  6861.   myColor.blue:=0;
  6862.   RGBForeColor(myColor); {set pen red}
  6863.   FrameRect(myRect); {draw in red}
  6864.  
  6865. Internally the Color Manager finds the best match to a color in TheGdevice’s current
  6866. color table, and sets up the current cGrafPort to draw in this color. At this point,
  6867. drawing operations can proceed using the selected colors.
  6868.  
  6869. The Color Manager routines described in this chapter are designed to operate on a
  6870. single gDevice. The Palette Manager can perform most of these operations across
  6871. multiple gDevices. Since the Palette Manager provides more general and portable
  6872. functionality, applications should use Palette Manager routines whenever possible.
  6873.  
  6874. The SetEntries routine is used to change any part of or all of the entries in a
  6875. device’s hardware Color Look-Up Table. The SaveEntries and RestoreEntries routines
  6876. can make temporary changes to the color table under very specialized circumstances
  6877. (such as a color selection dialog within an application). These routines aren’t
  6878. needed under normal application circumstances.
  6879.  
  6880. SaveEntries allows any combination of colorSpecs to be copied into a special colorTable.
  6881. RestoreEntries replaces the table created by SaveEntries into the graphics device.
  6882. Unlike SetEntries, these routines don’t perform invalidations of the device’s colorTable,
  6883. so they avoid causing invalidations of cached data structures. When these routines
  6884. are used, the application must take responsibility for rebuilding and restoring
  6885. auxiliary structures as necessary.
  6886.  
  6887. By convention, when using SetEntries or RestoreEntries, white should be located at
  6888. color table position 0, and black should be stored in the last color table position
  6889. available, whether it is 1, 3, 15, or 255. The Palette Manager also enforces this
  6890. convention.
  6891.  
  6892. For precise control over color, or for dedicated color table entries, the Color
  6893. Manager routines maintain special information in device color tables. Using ProtectEntry
  6894. and ReserveEntry, an entry may be protected, which prevents SetEntries from further
  6895. changing the entry, or reserved, which makes the entry unavailable to be matched by
  6896. RGBForeColor and RGBBackColor. Routines that change the device table (SetEntries,
  6897. ProtectEntry, and ReserveEntry, but not RestoreEntries) will perform the appropriate
  6898. invalidations of QuickDraw data structures. The application must then redraw where
  6899. necessary.
  6900.  
  6901. To inquire if a color exists in a color table, use RealColor. This tells whether an
  6902. arbitrary color actually exists in the table for that gDevice.
  6903.  
  6904. Color2Index returns the index in the current device’s colorTable that is the best
  6905. match to the requested color. Index2Color performs the opposite function—it returns
  6906. the RGB of a particular index value. These routines can be useful when making copies
  6907. of the screen frame buffer. InvertColor finds the complement of the provided color.
  6908. GetSubTable performs a group Color2Index on a colorTable.
  6909.  
  6910. _______________________________________________________________________________
  6911.  
  6912.  
  6913. æKY Color…Manager…Routines
  6914. æC »COLOR MANAGER ROUTINES                                       ColorManager
  6915. _______________________________________________________________________________
  6916.  
  6917. The routines used for color drawing are covered in the chapter “Color
  6918. QuickDraw”. The Color Manager includes routines for color conversion, color table
  6919. management, and error handling.
  6920.  
  6921. _______________________________________________________________________________
  6922.  
  6923. »Color Conversion
  6924.  
  6925. FUNCTION Color2Index (rgb: RGBColor): LONGINT;
  6926.  
  6927. The Color2Index routine finds the best available approximation to a given absolute
  6928. color, using the list of search procedures in the current device record. It returns a
  6929. longint, which is a pixel value padded with zeros in the high word. Since the colorSpec.value
  6930. field is only a word, the result returned from Color2Index must be truncated to fit
  6931. into a colorSpec. In pixMaps the
  6932. .value is the low-order word of this index.
  6933.  
  6934. Color2Index shouldn’t be called from a custom search procedure.
  6935.  
  6936. PROCEDURE Index2Color (index: LONGINT; VAR rgb: RGBColor);
  6937.  
  6938. The Index2Color routine finds the RGB color corresponding to a given color table
  6939. index. The desired pixel value is passed and the corresponding RGB value is returned
  6940. in RGB. The routine takes a longint, which should be a pixel value padded with zeros
  6941. in the high word (normally the compiler does this automatically). Normally, the RGB
  6942. from the current device color table corresponding to the index is returned as the
  6943. RGBColor. Notice that this is not necessarily the same color that was originally
  6944. requested via RGBForeColor, RGBBackColor, SetCPixel, or Color2Index. This RGB is read
  6945. from the current gDevice color table.
  6946.  
  6947. PROCEDURE InvertColor (VAR theColor: RGBColor);
  6948.  
  6949. The InvertColor routine finds the complement of an absolute color, using the list of
  6950. complement procedures in the current device record. The default complement procedure
  6951. uses the 1’s complement of each component of the requested color.
  6952.  
  6953. FUNCTION RealColor (color: RGBColor) : BOOLEAN;
  6954.  
  6955. The RealColor routine tells whether a given absolute color actually exists in the
  6956. current device’s color table. This decision is based on the current resolution of the
  6957. inverse table. For example, if the current iTabRes is four, RealColor returns TRUE if
  6958. there exists a color that exactly matches the top four bits of red, green, and blue.
  6959.  
  6960. PROCEDURE GetSubTable (myColors: CTabHandle; iTabRes:INTEGER;
  6961.                        targetTbl: CTabHandle);
  6962.  
  6963. The GetSubTable routine takes a ColorTable pointed at by myColors, and maps each RGB
  6964. value into its nearest available match for each target table. These best matches are
  6965. returned in the colorSpec.value fields of myColors. The values returned are best
  6966. matches to the RGBColor in targetTbl and the returned indices are indices into targetTbl.
  6967. Best matches are calculated using Color2Index and all applicable rules apply. A
  6968. temporary inverse table is built, and then discarded. ITabRes controls the resolution
  6969. of the iTable that is built. If targetTbl is NIL, then the current device’s color
  6970. table is used, and the
  6971. device’s inverse table is used rather than building a new one. To provide a different
  6972. resolution than the current inverse table, provide an explicit targetTbl parameter;
  6973. don’t pass a NIL parameter.
  6974.  
  6975. Warning:  Depending on the requested resolution, building the inverse table
  6976.           can require large amounts of temporary space in the application
  6977.           heap:  twice the size of the table itself, plus a fixed overhead
  6978.           for each inverse table resolution of 3–15K bytes.
  6979.  
  6980. PROCEDURE MakeITable (colorTab: CTabHandle; inverseTab: ITabHandle;
  6981.                       res: INTEGER);
  6982.  
  6983. The MakeITable routine generates an inverse table based on the current contents of
  6984. the color table pointed to by CTabHandle, with a resolution of res bits per channel.
  6985. Reserved color table pixel values are not included in the resultant color table.
  6986. MakeITable tests its input parameters and will return an error in QDError if the
  6987. resolution is less than three or greater than five. Passing a NIL parameter to CTabHandle
  6988. or ITabHandle substitutes an appropriate handle from the current gDevice, while
  6989. passing 0 for res substitutes the current gDevice’s preferred table resolution. These
  6990. defaults can be used in any combination with explicit values, or with NIL parameters.
  6991.  
  6992. This routine allows maximum precision in matching colors, even if colors in the color
  6993. table differ by less than the resolution of the inverse table. Five-bit inverse
  6994. tables are not needed when drawing in normal QuickDraw modes. However, the new QuickDraw
  6995. transfer modes (add, subtract, blend, etc.) may require a
  6996. 5-bit inverse table for best results with certain color tables. MakeITable returns a
  6997. QDError if the destination inverse table memory cannot be allocated. The 'mitq'
  6998. resource governs how much memory is allocated for temporary internal structures; this
  6999. resource type is for internal use only.
  7000.  
  7001. Warning:  Depending on the requested resolution, building the inverse table
  7002.           can require large amounts of temporary space in the application
  7003.           heap:  twice the size of the table itself, plus a fixed overhead
  7004.           for each inverse table resolution of 3–15K bytes.
  7005.  
  7006. _______________________________________________________________________________
  7007.  
  7008. »Color Table Management
  7009.  
  7010. FUNCTION GetCTSeed : LONGINT;
  7011.  
  7012. The GetCTSeed function returns a unique seed value that can be used in the ctSeed
  7013. field of a color table created by an application. This seed value guarantees that the
  7014. color table will be recognized as distinct from the destination, and that color table
  7015. translation will be performed properly. The return value will be greater than the
  7016. value stored in minSeed.
  7017.  
  7018. PROCEDURE ProtectEntry (index: INTEGER; protect: BOOLEAN);
  7019.  
  7020. The ProtectEntry procedure protects or removes protection from an entry in the current
  7021. device’s color table, depending on the value of the protect parameter.  A protected
  7022. entry can’t be changed by other clients.  It returns a protection error if it attempts
  7023. to protect an already protected entry. However, it can remove protection from any
  7024. entry.
  7025.  
  7026. PROCEDURE ReserveEntry (index: INTEGER; reserve: BOOLEAN);
  7027.  
  7028. The ReserveEntry procedure reserves or dereserves an entry in the current color
  7029. table, depending on the value of the reserve parameter.  A reserved entry cannot be
  7030. matched by another client’s search procedure, and will never be returned to another
  7031. client by Color2Index or other routines that depend on it
  7032. (such as RGBForeColor, RGBBackColor, SetCPixel, and so forth).  You could use this
  7033. routine to selectively protect a color for color table animation.
  7034.  
  7035. ReserveEntry copies the low byte of gdID into the low byte of ColorSpec.value when
  7036. reserving an entry, and leaves the high byte alone. It acts like a selective protection,
  7037. and does not allow any changes if the current gdID is different than the one in the
  7038. colorSpec.value field of the reserved entry. If a requested match is already reserved,
  7039. ReserveEntry returns a protection error. Any entry can be dereserved.
  7040.  
  7041. PROCEDURE  SetEntries(start, count: INTEGER; aTable: CSpecArray);
  7042.  
  7043. The SetEntries procedure sets a group of color table entries for the current gDevice,
  7044. starting at a given position for the specified number of entries. The pointer aTable
  7045. points into a cSpecArray, not into a color table.  The colorSpec.value field of the
  7046. entries must be in the logical range for the target card’s assigned pixel depth.
  7047. Thus, with a 4-bit pixel size, the colorSpec.value fields should be in the range 1 to
  7048. 15. With an 8-bit pixel size the range is 0 to 255.  Note that all values are zero-based;
  7049. for example, to set three entries, pass two in the count parameter.
  7050.  
  7051. Note:  Palette Manager routines should be used instead of the SetEntries
  7052.        routine for applications that will run in a multiscreen or
  7053.        multitasking environment.
  7054.  
  7055. The SetEntries positional information works in logical space, rather than in the
  7056. actual memory space used by the hardware. Requesting a change at position four in the
  7057. color table may not modify color table entry four in the hardware, but it does correctly
  7058. change the color on the screen for any pixels with a value of four in the video card.
  7059. The SetEntries mode characterized by a start position and a length is called sequence
  7060. mode. In this case, new colors are sequentially loaded into the hardware in the same
  7061. order as the aTable, the clientID fields for changed entries are copied from the
  7062. current device’s gdID field, and the colorSpec.value fields are ignored.
  7063.  
  7064. The other SetEntries mode is called index mode. It allows the cSpecArray to specify
  7065. where the data will be installed on an entry-by-entry basis. To use this mode, pass
  7066. –1 for the start position, with a valid count and a pointer to the cSpecArray. Each
  7067. entry is installed into the color table at the position specified by the colorSpec.value
  7068. field of each entry in the cSpecArray. In the current device’s color table, all
  7069. changed entries’ colorSpec.value fields are assigned the gdID value.
  7070.  
  7071. When color table entries are changed, all cached fonts are invalidated, and the seed
  7072. number is changed so that the next drawing operation will rebuild the inverse table.
  7073. If any of the requested entries are protected or out of range, a protection error is
  7074. returned, and nothing happens. If a requested entry is reserved, it can only be
  7075. changed if the current gdID matches the low byte of the intended ColorSpec.value
  7076. field.
  7077.  
  7078. PROCEDURE SaveEntries (srcTable: CTabHandle; ResultTable: CTabHandle;
  7079.                        VAR  selection: ReqListRec);
  7080.  
  7081. SaveEntries saves a selection of entries from srcTable into resultTable. The entries
  7082. to be set are enumerated in the selection parameter, which uses the ReqListRec data
  7083. structure shown below. (These values are offsets into colorTable, not the contents of
  7084. the colorSpec.value field.)
  7085.  
  7086. TYPE
  7087.   ReqListRec = RECORD
  7088.                  reqLSize:  INTEGER;                 {request list size –1}
  7089.                  reqLData:  ARRAY [0..0] of INTEGER  {request list data}
  7090.                END;
  7091.  
  7092. If an entry is not present in srcTable, then that position of the requestList is set
  7093. to colReqErr, and that position of resultTable has random values returned. If one or
  7094. more entries are not found, then an error code is posted to QDError; however, for
  7095. every entry in selection which is not colReqErr, the values in resultTable are valid.
  7096. Note that srcTable and selection are assumed to have the same number of entries.
  7097.  
  7098. SaveEntries optionally allows NIL as its source color table parameter. If NIL is
  7099. used, the current device’s color table is used as the source. The output of SaveEntries
  7100. is the same as the input for RestoreEntries, except for the order.
  7101.  
  7102. PROCEDURE RestoreEntries (srcTable:CTabHandle;DstTable:CTabHandle;
  7103.                           VAR selection:ReqListRec);
  7104.  
  7105. RestoreEntries sets a selection of entries from srcTable into dstTable, but doesn’t
  7106. rebuild the inverse table. The dstTable entries to be set are enumerated in the
  7107. selection parameter, which uses the ReqListRec data structure shown in the SetEntries
  7108. routine description. (These values are offsets into the srcTable, not the contents of
  7109. the colorSpec.value field.)
  7110.  
  7111. If a request is beyond the end of the dstTable, that position of the requestList is
  7112. set to colReqErr, and an error is returned. Note that srcTable and selection are
  7113. assumed to have the same number of entries.
  7114.  
  7115. If dstTbl is NIL, or points to the device color table, the current device’s color
  7116. table is updated, and the hardware is updated to these new colors. The seed is not
  7117. changed, so no invalidation occurs (this may cause RGBForeColor to act strangely).
  7118. This routine ignores protection and reservation of color table entries.
  7119.  
  7120. Generally, the Palette Manager is used to give an application its own set of colors;
  7121. use of RestoreEntries should be limited to special-purpose applications. RestoreEntries
  7122. allows you to change the colorTable without changing the ctSeed for the affected
  7123. colorTable. You can execute the application code and then use RestoreEntries to put
  7124. the original colors back in. However, in some cases things in the background may
  7125. appear in the wrong colors, since they were never redrawn. To avoid this, the application
  7126. must build its own new inverse table and redraw the background. If RestoreEntries
  7127. were then used, the ctSeed would have to be explicitly changed to clean up correctly.
  7128.  
  7129. _______________________________________________________________________________
  7130.  
  7131. »Error Handling
  7132.  
  7133. FUNCTION QDError: INTEGER;
  7134.  
  7135. The QDError routine returns the error result from the last QuickDraw or Color Manager
  7136. call.  This routine is even more useful with 32-Bit QuickDraw.  It is important that
  7137. you check for errors after every QuickDraw call.  For more information, see the
  7138. 32-Bit QuickDraw documentation.
  7139.  
  7140. _______________________________________________________________________________
  7141.  
  7142.  
  7143. æKY Custom…Search…and…Complement…Functions
  7144. æC »CUSTOM SEARCH AND COMPLEMENT FUNCTIONS                       ColorManager
  7145. _______________________________________________________________________________
  7146.  
  7147. The custom search function allows an application to override the inverse table matching
  7148. code. The desired color is specified in the RGBColor field of a ColorSpec record and
  7149. passed via a pointer on the stack; the procedure returns the corresponding pixel
  7150. value in the ColorSpec.value field.
  7151.  
  7152. A custom search routine can provide its own matching rules. For instance, you might
  7153. want to map all levels of green to a single green on a monitor. To do this, you could
  7154. write and install a custom search procedure that is passed the RGB under question by
  7155. the Color Manager. It can then analyze the color, and if it decides to act on this
  7156. color, it can return the index of the desired shade of green. Otherwise, it can pass
  7157. the color back to the Color Manager for matching, using the normal inverse table
  7158. routine.
  7159.  
  7160. Many applications can share the same graphics device, each with its own custom search
  7161. procedure.  The procedures are chain elements in a linked list beginning in the
  7162. gdSearchProc field of the gDevice port:
  7163.  
  7164. TYPE
  7165.   SProcHndl = ^SProcPtr;
  7166.   SProcPtr  = ^SProcRec;;
  7167.   SProcRec  = RECORD
  7168.                 nxtSrch:   SProcHndl;  {handle to next sProcRec}
  7169.                 srchProc:  ProcPtr     {pointer to search procedure}
  7170.               END;
  7171.  
  7172. Any number of search procedures can be installed in a linked list, each element of
  7173. which will be called sequentially by the Color Manager, and given the chance to act
  7174. or pass on the color. Since each device is a shared resource, a simple method (the
  7175. gdID) is provided to identify the caller to the search procedures, as well as routines
  7176. to add and delete custom procedures from the linked list.
  7177.  
  7178. The interface is as follows:
  7179.  
  7180. FUNCTION SearchProc (rgb: RGBColor; VAR position: LONGINT): BOOLEAN;
  7181.  
  7182. When attempting to approximate a color, the Color Manager calls each search procedure
  7183. in the list until the boolean value returns as TRUE.  The index value of the closest
  7184. match is returned by the position parameter.  If no search procedure installed in the
  7185. linked list returns TRUE, the Color Manager calls the default search procedure.
  7186.  
  7187. The application can also supply a custom complement procedure to find the complement
  7188. of a specified color. Complement procedures work the same as search procedures, and
  7189. are kept in a list beginning in the gDevice port’s gdCompProc field.
  7190.  
  7191. TYPE
  7192.   CProcHndl = ^CProcPtr;
  7193.   CProcPtr  = ^CProcRec;
  7194.   CProcRec  = RECORD
  7195.                 nxtComp:   CProcHandle;  {pointer to next CProcRec}
  7196.                 compProc:  ProcPtr       {pointer to complement procedure}
  7197.               END;
  7198.  
  7199. The default complement procedure simply uses the 1’s complement of the RGB color
  7200. components before looking them up in the inverse table. The interface is as follows:
  7201.  
  7202. FUNCTION CompProc (VAR rgb: RGBColor) : BOOLEAN;
  7203.  
  7204. _______________________________________________________________________________
  7205.  
  7206. »Operations on Search and Complement Functions
  7207.  
  7208. PROCEDURE AddSearch (searchProc: ProcPtr);
  7209. PROCEDURE AddComp   (compProc: ProcPtr);
  7210.  
  7211. The AddSearch and AddComp routines add a procedure to the head of the current device
  7212. record’s list of search or complement procedures. These routines allocate an SProcRec
  7213. or CProcRec.
  7214.  
  7215. PROCEDURE DelSearch (searchProc: ProcPtr);
  7216. PROCEDURE DelComp   (compProc: ProcPtr);
  7217.  
  7218. The DelSearch and DelComp procedures remove a custom search or complement procedure
  7219. from the current device record’s list of search or complement procedures. These
  7220. routines dispose of the chain element, but do nothing to the procPtr.
  7221.  
  7222. PROCEDURE SetClientID (id: INTEGER);
  7223.  
  7224. The SetClientID procedure sets the gdID field in the current device record to identify
  7225. this client program to its search and complement procedures.
  7226.  
  7227. _______________________________________________________________________________
  7228.  
  7229.  
  7230. æKY Summary…of…the…Color…Manager
  7231. æC »SUMMARY OF THE COLOR MANAGER                                 ColorManager
  7232. _______________________________________________________________________________
  7233.  
  7234. Constants
  7235.  
  7236. CONST
  7237.   minSeed = 1023;    {minimum seed value for ctSeed}
  7238.  
  7239. _______________________________________________________________________________
  7240.  
  7241. Data Types
  7242.  
  7243. TYPE
  7244.   ITabHandle = ^ITabPtr;
  7245.   ITabPtr    = ^ITab;
  7246.   ITab       = RECORD
  7247.                  iTabSeed:  LONGINT;    {copy of color table seed}
  7248.                  iTabRes:   INTEGER;    {resolution of table}
  7249.                  iTTable:   ARRAY[0..0] OF SignedByte {byte color }
  7250.                                         { table index values}
  7251.                END;
  7252.  
  7253.   SProcHndl = ^SProcPtr;
  7254.   SProcPtr  = ^SProcRec;;
  7255.   SProcRec  = RECORD
  7256.                 nxtSrch:   SProcHndl;  {handle to next sProcRec}
  7257.                 srchProc:  ProcPtr     {pointer to search procedure}
  7258.               END;
  7259.  
  7260.   CProcHndl = ^CProcPtr;
  7261.   CProcPtr  = ^CProcRec;
  7262.   CProcRec  = RECORD
  7263.                 nxtComp:   CProcHandle;  {pointer to next CProcRec}
  7264.                 compProc:  ProcPtr       {pointer to complement procedure}
  7265.               END;
  7266.  
  7267.   ReqListRec = RECORD
  7268.                  reqLSize:  INTEGER;                 {request list size –1}
  7269.                  reqLData:  ARRAY [0..0] of INTEGER  {request list data}
  7270.                END;
  7271.  
  7272. _______________________________________________________________________________
  7273.  
  7274. Routines
  7275.  
  7276. Color Conversion
  7277.  
  7278. FUNCTION  Color2Index  (VAR rgb: RGBColor): LONGINT;
  7279. PROCEDURE Index2Color  (index: LONGINT; VAR rgb: RGBColor);
  7280. PROCEDURE InvertColor  (VAR theColor: RGBColor);
  7281. FUNCTION  RealColor    (color: RGBColor) : BOOLEAN;
  7282. PROCEDURE GetSubTable  (myColors: CTabHandle; iTabRes: INTEGER;
  7283.                         targetTbl:CTabHandle);
  7284. PROCEDURE MakeITable   (colorTab: CTabHandle; inverseTab: ITabHandle;
  7285.                         res: INTEGER);
  7286.  
  7287. Color Table Management
  7288.  
  7289. FUNCTION  GetCTSeed: LONGINT;
  7290. PROCEDURE ProtectEntry    (index: INTEGER; protect: BOOLEAN);
  7291. PROCEDURE ReserveEntry    (index: INTEGER; reserve: BOOLEAN);
  7292. PROCEDURE SetEntries      (start, count: INTEGER; aTable: cSpecArray);
  7293. PROCEDURE RestoreEntries  (srcTable:CTabHandle;dstTable:CTabHandle;
  7294.                            VAR selection:ReqListRec);
  7295. PROCEDURE SaveEntries     (srcTable:CTabHandle;resultTable:CTabHandle; VAR selection:ReqListRec)
  7296.  
  7297. Operations on Search and Complement Functions
  7298.  
  7299. PROCEDURE AddSearch    (searchProc: ProcPtr);
  7300. PROCEDURE AddComp      (compProc: ProcPtr);
  7301. PROCEDURE DelSearch    (searchProc: ProcPtr);
  7302. PROCEDURE DelComp      (compProc: ProcPtr);
  7303. PROCEDURE SetClientID  (id: INTEGER);
  7304.  
  7305. Error Handling
  7306.  
  7307. FUNCTION QDError: INTEGER;
  7308.  
  7309. _______________________________________________________________________________
  7310.  
  7311. Assembly Language Information
  7312.  
  7313. Constants
  7314.  
  7315. minSeed    EQU    1023  ;minimum ctSeed value
  7316.  
  7317. ITab structure
  7318.  
  7319. iTabSeed   EQU    $0    ;[long] ID of owning color table
  7320. iTabRes    EQU    $4    ;[word] client ID
  7321. iTTable    EQU    $6    ;table of indices starts here
  7322.                         ;in this version, entries are BYTE
  7323.  
  7324. SProcRec structure
  7325.  
  7326. nxtSrch    EQU    $0    ;[pointer] link to next proc
  7327. srchProc   EQU    $4    ;[pointer] pointer to routine
  7328.  
  7329. CProcRec structure
  7330.  
  7331. nxtComp    EQU    $0    ;[pointer] link to next proc
  7332. compProc   EQU    $4    ;[pointer] pointer to routine
  7333.  
  7334. Request list structure
  7335.  
  7336. reqLSize   EQU    0    ;[word] request list size –1
  7337. reqLData   EQU    2    ;[word] request list data
  7338.  
  7339. Further Reference:
  7340. _______________________________________________________________________________
  7341. Color QuickDraw
  7342. Graphics Devices
  7343. Palette Manager
  7344. Color Picker Package
  7345. 32-Bit QuickDraw Documentation
  7346.  
  7347. æKY ColorPickerPackage
  7348. æC 
  7349. _______________________________________________________________________________
  7350.  
  7351. COLOR PICKER PACKAGE
  7352. _______________________________________________________________________________
  7353.  
  7354. About…the…Color…Picker…Chapter
  7355. About…the…Color…Picker…Package
  7356. Color…Models
  7357.     The…RGB…Model
  7358.     The…CMYK…Model
  7359.     The…HLS…and…HSV…Models
  7360.     Color…Models…in…the…Dialog…Box
  7361. Using…the…Color…Picker…Package
  7362.     Presenting…the…Dialog…Box
  7363.     Conversion…Facilities
  7364. Color…Picker…Routines
  7365.     Displaying…the…Color…Picker…Dialog…Box
  7366.     Converting…Between…Color…Models
  7367.     Converting…Between…SmallFract…and…Fixed…Values
  7368. Summary…of…the…Color…Picker…Package
  7369.     Color…Picker…Package…Constants
  7370.     Color…Picker…Package…Data…Types
  7371.     Color…Picker…Package…Routines
  7372.     Assembly…Language…Information…for…Color…Picker…Package
  7373. _______________________________________________________________________________
  7374.  
  7375.  
  7376.  
  7377. æKY About…the…Color…Picker…Chapter
  7378. æC »ABOUT THIS CHAPTER                                                Color Picker Package
  7379. _______________________________________________________________________________
  7380.  
  7381. This chapter describes the Color Picker Package, a utility with which
  7382. applications can offer users a standard dialog box for choosing a color. You
  7383. should be familiar with the material in the Graphics Overview chapter in this
  7384. volume, especially the discussion of direct and indexed video devices. Effective
  7385. use of the Color Picker will also require familiarity with Color QuickDraw,
  7386. described in Volume V of Inside Macintosh, and in this volume. 
  7387.  
  7388. This chapter supersedes the description of the Color Picker in Volume V.
  7389.  
  7390. You need to read this chapter if your application uses the color system
  7391. introduced with Color QuickDraw (rather than the 8-color system available with
  7392. the original QuickDraw), and you need to solicit color choices from your users.
  7393. If your application limits user selection to a specific list of colors, you may
  7394. need to construct your own dialog box for color selection using Palette Manager
  7395. routines, as the Color Picker allows the user to choose colors from the entire
  7396. range available with Color QuickDraw’s 48-bit RGB values.
  7397.  
  7398. _______________________________________________________________________________
  7399.  
  7400. æKY About…the…Color…Picker…Package
  7401. æC »ABOUT THE COLOR PICKER PACKAGE                                    Color Picker Package
  7402. _______________________________________________________________________________
  7403.  
  7404. The Color Picker Package provides you with a standard way of soliciting a color
  7405. choice from the user. When an application calls the Color Picker’s GetColor
  7406. function, the Color Picker presents its dialog box to the user, as shown in
  7407. Figure 17-1. 
  7408.  
  7409. When the user is satisfied with a chosen color and clicks the OK button,
  7410. GetColor returns that color to your application as an RGB value. 
  7411.  
  7412. ø 17.1  The Color Picker dialog box
  7413.  
  7414. The Color Picker also has utility routines for converting between RGB values and
  7415. several other color systems, and for converting between the integers Color
  7416. QuickDraw uses for RGB colors and the SmallFract values the Color Picker uses
  7417. with alternate color models.
  7418.  
  7419. This chapter describes the color models the Color Picker works with, and how you
  7420. set up and present the dialog box to users.
  7421.  
  7422. _______________________________________________________________________________
  7423.  
  7424. æKY Color…Models
  7425. æC »COLOR MODELS                                                      Color Picker Package
  7426. _______________________________________________________________________________
  7427.  
  7428. Both QuickDraw and standard video monitors work with a red, green, blue (RGB)
  7429. color model, but in graphic arts and design other color models, such as HLS 
  7430. (hue, lightness, saturation) or HSV (hue, saturation, value) are used, and in
  7431. printing the CMYK (cyan, magenta, yellow, and black) model predominates. Great
  7432. books have been written about color; this section presents a quick survey of the
  7433. models with which the Color Picker works.
  7434.  
  7435. _______________________________________________________________________________
  7436.  
  7437. æKY The…RGB…Model
  7438. æC »The RGB Model                                                     Color Picker Package
  7439. _______________________________________________________________________________
  7440.  
  7441. In the RGB model, the three colors are additive. The more of each color you add
  7442. the closer the resulting color is to white. This is the way light-produced
  7443. colors work; turning on the red, green, and blue phosphors of a television
  7444. screen produces white, as does shining lights of red, green, and blue upon a
  7445. stage. 
  7446.  
  7447. The QuickDraw data structure for an RGBColor record is
  7448.  
  7449.   RGBColor = RECORD
  7450.   red:     Integer;  {red component}
  7451.   green:   Integer;  {green component}
  7452.   blue:    Integer   {blue component}
  7453.   END;
  7454.  
  7455. The frontispiece of Volume V of Inside Macintosh shows a color cube that
  7456. represents the values possible in an RGB system. Figure 17-2 is a
  7457. black-and-white representation of that cube.
  7458.  
  7459.  
  7460.     
  7461. ø 17.2  The RGB Color Cube
  7462.  
  7463. Starting at one corner, with zero values for each color, is black. Increasing
  7464. any one of the values produces shades of that color, increasing its saturation.
  7465. Increasing all three values equally generates a diagonal line across the cube
  7466. toward full value (65,535) for each, which is white. Values on that diagonal are
  7467. shades of gray; values off the line in any direction are colors. For example,
  7468. pink in the RGB model would be full red with some equal amount of green and
  7469. blue, in effect moving from the black corner of the color cube up along the edge
  7470. to full red, then traversing a diagonal across the top face from red toward
  7471. white. 
  7472.  
  7473.     
  7474. ø 17.3  Getting to pink
  7475.  
  7476. _______________________________________________________________________________
  7477.  
  7478. æKY The…CMYK…Model
  7479. æC »The CMYK Model                                                    Color Picker Package
  7480. _______________________________________________________________________________
  7481.  
  7482. In the CMYK model, which is used by the print world, the three colors and black
  7483. are subtractive: increasing values moves the result closer to black. This is
  7484. intuitive for printing, which is usually done on white paper—to get white, don’t
  7485. print anything. In theory, black could be achieved by mixing full values of
  7486. cyan, magenta, and yellow, but purity in chemicals is more problematic than with
  7487. light, and four-color print processes use black as well. The Color Picker’s
  7488. CMYColor data structure defines only the three colors. It uses SmallFract
  7489. values, which are the fractional part of Fixed values, as described in Color
  7490. Picker Conversion Facilities.
  7491.  
  7492.   CMYColor  = RECORD
  7493.   cyan:     SmallFract;
  7494.   magenta:  SmallFract;
  7495.   yellow:   SmallFract
  7496.   END;
  7497.  
  7498.  Note that cyan, magenta, and yellow are complements of red, green, and blue. 
  7499.  
  7500. ø 17.4  CMY on the color cube
  7501.  
  7502. _______________________________________________________________________________
  7503.  
  7504. æKY The…HLS…and…HSV…Models
  7505. æC »The HLS and HSV Models                                            Color Picker Package
  7506. _______________________________________________________________________________
  7507.  
  7508. The components of the HLS and HSV models are not three diverse colors, as in RGB
  7509. and CMY. The HLS and HSV models separate color, or hue, from brightness and
  7510. saturation. 
  7511.  
  7512. Brightness is a measure of how much black is in a color, saturation is a measure
  7513. of how much white it contains. Hue is indicated by an arbitrary assignment of
  7514. numbers to colors. The amount of that hue is indicated by a saturation value,
  7515. and the brightness of the color is a third value. The best representation for
  7516. such a system is an inverted cone, in which hues vary around the perimeter,
  7517. where they are most highly saturated, and brightness increases from the tip of
  7518. the cone to the disk. The gray line from black to white begins at the bottom-tip
  7519. and runs up through the cone to the center of the disk. 
  7520.       
  7521. ø 17.5  The HLS/HSV color cone
  7522.  
  7523. This is the model portrayed in the Color Picker’s dialog box. The disk is shown
  7524. full face, the hues are at their most saturated around the rim, and the
  7525. brightness line down the cone is controlled by the scroll bar.
  7526.  
  7527. In the Color Picker’s color wheel the value for pure red is 0, pure green is
  7528. 21,845, and pure blue is 43,690. The amount of black is set by the value for
  7529. brightness (meaning lightness in HLS, value in HSV), and the amount of color in
  7530. the mix is set by saturation. Pink in the HLS or HSV system would be obtained by
  7531. setting hue to red, saturation to some amount less than full, and brightness to
  7532. full.
  7533.  
  7534. The HLS and HSV systems are sufficiently similar that the Color Picker can treat
  7535. them as one by a simple expedient: the HLS model is treated by the Picker as if
  7536. it were ordered HSL; this puts hue and saturation in the same relative positions
  7537. in the data structures of both models.  
  7538.  
  7539. HSVColor = RECORD
  7540. hue:         SmallFract;  {fraction of circle, red at 0}
  7541. saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  7542. value:       SmallFract   {0-1, 0 is black, 1 is max intensity}
  7543. END;
  7544.  
  7545. HSLColor = RECORD
  7546. hue:         SmallFract;  {fraction of circle, red at 0}
  7547. saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  7548. lightness:   SmallFract   {0-1, 0 is black, 1 is white}
  7549. END;
  7550. _______________________________________________________________________________
  7551.  
  7552. æKY Color…Models…in…the…Dialog…Box
  7553. æC »Color Models in the Dialog Box                                    Color Picker Package
  7554. _______________________________________________________________________________
  7555.  
  7556. The controls in the dialog box are designed for use in the HSL or HSV models:
  7557. hue is chosen by moving the cursor around the color wheel, saturation by moving
  7558. in or out from the center, and brightness (value or lightness) is specified by
  7559. the scroll bar at the right. The way RGB values vary in response to the dialog
  7560. controls is not intuitive, but it can be instructive on how the models relate.
  7561.  
  7562. The dialog box cannot exactly match the print world’s additive effect, and it
  7563. does not offer CMYK controls, but routines for converting between RGB and CMY 
  7564. (cyan, magenta, yellow, without a black component) are included in the Color
  7565. Picker Package.
  7566.  
  7567. _______________________________________________________________________________
  7568.  
  7569. æKY Using…the…Color…Picker…Package
  7570. æC »USING THE COLOR PICKER PACKAGE                                    Color Picker Package
  7571. _______________________________________________________________________________
  7572.  
  7573. Most developers will only use the Color Picker Package to display the Color
  7574. Picker’s dialog box.  A few developers may need to use the color model and
  7575. SmallFract conversion routines.
  7576.  
  7577. _______________________________________________________________________________
  7578.  
  7579. æKY Presenting…the…Dialog…Box
  7580. æC »Presenting the Dialog Box                                         Color Picker Package
  7581. _______________________________________________________________________________
  7582.  
  7583. Your program can present a user with the Color Picker dialog box, shown in
  7584. Figure 1, by calling the Color Picker’s GetColor function.
  7585.  
  7586. When called by an application, the Color Picker displays the dialog box,
  7587. including prompt text, which appears in the upper-left corner, and the initial
  7588. color, which appears in the lower of the two rectangles below the prompt. The
  7589. color being picked, in the upper rectangle, ranges over the entire color space
  7590. in response to the controls in the rest of the dialog box. Your application can
  7591. supply the prompt text, an initial color, the location of the upper-left corner
  7592. of the dialog box window, and whether it should appear on the main or deepest
  7593. screen.
  7594.  
  7595. The two groups of numeric fields (Hue/Saturation/Brightness and Red/Green/Blue)
  7596. show the parameters of the color being picked in the two color systems. The user
  7597. may increase or decrease the values using the arrow controls or enter values
  7598. directly into any of the six fields.
  7599.  
  7600. The range for all of the component values is 0 to 65,535. Larger values are
  7601. clipped to 65,535 after the user exits the field. When the user is increasing or
  7602. decreasing the hue using the arrow controls, 0 wraps around to 65,535, so the
  7603. user can circumnavigate the wheel with arrow controls just as with the cursor.
  7604. The hue value for pure red is 0; pure green is 21,845; pure blue is 43,690.
  7605.  
  7606. The user may select a single RGB value from Color QuickDraw’s entire range of
  7607. 248 color values. 
  7608.  
  7609. On black-and-white hardware (or in less than 4-bit mode), the display appears in
  7610. black and white; the Color Picker returns the RGB value selected, but does not
  7611. call any color routines in the course of responding to user actions.
  7612.   
  7613. On devices with a variable CLUT, the Color Picker temporarily borrows a color
  7614. table entry to display the exact color in the rectangle that shows the color
  7615. currently being picked. (As a result, when your application subsequently
  7616. displays the user’s chosen color, if you let the Color Manager approximate the
  7617. user’s value the result will probably differ somewhat from the one picked.)  The
  7618. Color Picker restores the color environment when it is done.
  7619.  
  7620. _______________________________________________________________________________
  7621.  
  7622. æKY Conversion…Facilities
  7623. æC »Conversion Facilities                                             Color Picker Package
  7624. _______________________________________________________________________________
  7625.  
  7626. In addition to the GetColor function that puts up the Color Picker dialog box,
  7627. the Color Picker provides six procedures for converting between RGB and the CMY,
  7628. HLS, and HSV color systems; and two functions that convert between SmallFract
  7629. and fixed numbers. Most developers will use only the GetColor function.
  7630.  
  7631. The CMY, HSL, and HSV structures are defined by ColorPicker with SmallFract
  7632. values rather than INTEGER values (as used in RGBColor). A SmallFract value is
  7633. the fractional part of a Fixed number, which is the low-order word. The Integer
  7634. values in RGBColor are actually used as unsigned integer-sized values; by using
  7635. SmallFract values, the ColorPicker avoids sign extension problems in the
  7636. conversion math. The Color Picker provides two functions for converting between
  7637. SmallFract and fixed numbers. Most developers will not need to use these
  7638. facilities.
  7639.  
  7640. _______________________________________________________________________________
  7641.  
  7642. æKY Color…Picker…Routines
  7643. æC »COLOR PICKER ROUTINES                                             Color Picker Package
  7644. _______________________________________________________________________________
  7645.  
  7646. The following cards describe the Color Picker routines.
  7647. _______________________________________________________________________________
  7648.  
  7649. æKY Displaying…the…Color…Picker…Dialog…Box
  7650. æC »Displaying the Color Picker Dialog Box                            Color Picker Package
  7651. _______________________________________________________________________________
  7652.  
  7653. FUNCTION GetColor (where: Point; prompt: Str255; inColor: RGBColor; VAR        
  7654.  
  7655.                    outColor: RGBColor) : BOOLEAN;
  7656.  
  7657. The GetColor function displays the Color Picker dialog box on the screen, with
  7658. its upper-left corner located at the point you designate with the where
  7659. parameter. The Color Picker Package will display the dialog box and accept color
  7660. selection on any screen, not just the main screen. If where = (0,0), the dialog
  7661. box is positioned neatly on the main screen—centered horizontally and with
  7662. one-third of the empty space above the box and two-thirds below, whatever the
  7663. screen size. If an application supplies a where parameter of -1,-1, the Color
  7664. Picker will center the dialog box on what the Color Picker determines to be the
  7665. best screen, maximizing for depth and color.  
  7666.  
  7667. The prompt string is displayed in the upper-left corner of the dialog box. The
  7668. inColor parameter is the starting color, which the user may want for comparison;
  7669. it is displayed immediately below the current output color (the one the user is
  7670. picking). The OutColor parameter is set to the last color value the user picks,
  7671. if and only if the user clicks OK. On entry, it is treated as undefined, so the
  7672. output color sample originally matches the input. Although the color being
  7673. picked may vary widely, the input color sample remains fixed, and clicking in
  7674. the input sample resets the output color sample to match it.
  7675.  
  7676. GetColor returns TRUE if the user exits by clicking the OK button or FALSE if
  7677. the user cancels.
  7678.  
  7679. _______________________________________________________________________________
  7680.  
  7681. æKY Converting…Between…Color…Models
  7682. æC »Converting Between Color Models                                   Color Picker Package
  7683. _______________________________________________________________________________
  7684.  
  7685. These six routines offer conversions between RGB on the one hand and CMY, HSV,
  7686. or HSL on the other.
  7687.  
  7688. PROCEDURE  CMY2RGB (cColor: CMYColor; VAR rColor: RGBColor);
  7689.  
  7690. The CMY2RGB procedure converts a CMYColor record to an RGBColor record.
  7691.  
  7692. PROCEDURE  HSL2RGB (hColor: HSLColor; VAR rColor: RGBColor);
  7693.  
  7694. The HSL2RGB procedure converts an HSLColor record to an RGBcolor record.
  7695.  
  7696. PROCEDURE  HSV2RGB (hColor: HSVColor; VAR rColor: RGBColor);
  7697.  
  7698. The HSV2RGB procedure converts an HSVColor record to an RGBColor record.
  7699.  
  7700. PROCEDURE  RGB2CMY (rColor: RGBColor; VAR cColor: CMYColor);
  7701.  
  7702. The RGB2CMY procedure converts an RGBColor record to a CMYColor record.
  7703.  
  7704. PROCEDURE  RGB2HSL (rColor: RGBColor; VAR hColor: HSLColor);
  7705.  
  7706. The RGB2HSL procedure converts an RGBColor record to an HSLColor record.
  7707.  
  7708. PROCEDURE  RGB2HSV (rColor: RGBColor; VAR hColor: HSVColor);
  7709.  
  7710. The RGB2HSV procedure converts an RGBColor record to an HSVColor record.
  7711.  
  7712. _______________________________________________________________________________
  7713.  
  7714. æKY Converting…Between…SmallFract…and…Fixed…Values
  7715. æC »Converting Between SmallFract and Fixed Values                    Color Picker Package
  7716. _______________________________________________________________________________
  7717.  
  7718. A SmallFract value can represent a value between 0 and 65,535. They can be
  7719. assigned directly to and from Integers.
  7720.   
  7721. FUNCTION SmallFract2Fix(s: SmallFract): Fixed;
  7722.  
  7723. The SmallFract2Fix function converts a SmallFract value to a fixed integer. 
  7724.  
  7725. FUNCTION Fix2SmallFract(f: Fixed): SmallFract;
  7726.  
  7727. The Fix2SmallFract function converts a fixed integer to a SmallFract value. 
  7728. _______________________________________________________________________________
  7729.  
  7730. æKY Summary…of…the…Color…Picker…Package
  7731. æC »SUMMARY OF THE COLOR PICKER PACKAGE                               Color Picker Package
  7732. _______________________________________________________________________________
  7733.  
  7734. The following cards summarize the constants, data types, and routines for the
  7735. Color Picker Package.
  7736. _______________________________________________________________________________
  7737.  
  7738. æKY Color…Picker…Package…Constants
  7739. æC »Constants                                                         Color Picker Package
  7740. _______________________________________________________________________________
  7741.  
  7742. CONST
  7743.  
  7744. MaxSmallFract  =  $0000FFFF;  {maximum SmallFract value, as LONGINT}
  7745. _______________________________________________________________________________
  7746.  
  7747. æKY  Color…Picker…Package…Data…Types
  7748. æC »Data Types                                                        Color Picker Package
  7749. _______________________________________________________________________________
  7750.  
  7751. TYPE
  7752. SmallFract = INTEGER;  {unsigned fraction between 0 and 1}
  7753.   HSVColor  = RECORD
  7754.     hue:         SmallFract;  {fraction of circle, red at 0}
  7755.     saturation:  SmallFract;  {0-1, 0 is gray, 1 is pure color}
  7756.     value:       SmallFract  {0-1, 0 is black, 1 is max intensity}
  7757.   END;
  7758.  
  7759.   HSLColor  = RECORD
  7760.   hue:          SmallFract;  {fraction of circle, red at 0}
  7761.   saturation:   SmallFract;  {0-1, 0 is gray, 1 is pure color}
  7762.   lightness:    SmallFract  {0-1, 0 is black, 1 is white}
  7763.   END;
  7764.  
  7765.   CMYColor  = RECORD   {CMY and RGB are complements}
  7766.   cyan:         SmallFract;
  7767.   magenta:      SmallFract;
  7768.   yellow:       SmallFract
  7769.   END;
  7770. _______________________________________________________________________________
  7771.  
  7772. æKY Color…Picker…Package…Routines
  7773. æC »Routines                                                          Color Picker Package
  7774. _______________________________________________________________________________
  7775.  
  7776. Displaying the Dialog Box
  7777.  
  7778. FUNCTION GetColor  (where: Point; prompt: Str255; inColor: RGBColor; VAR
  7779. outColor: RGBColor) : BOOLEAN;
  7780.  
  7781. Converting Between Color Models
  7782.  
  7783. PROCEDURE  CMY2RGB  (cColor: CMYColor; VAR rColor: RGBColor);
  7784. PROCEDURE  HSL2RGB  (hColor: HSLColor; VAR rColor: RGBColor);
  7785. PROCEDURE  HSV2RGB  (hColor: HSVColor; VAR rColor: RGBColor);
  7786. PROCEDURE  RGB2CMY  (rColor: RGBColor; VAR cColor: CMYColor);
  7787. PROCEDURE  RGB2HSL  (rColor: RGBColor; VAR hColor: HSLColor);
  7788. PROCEDURE  RGB2HSV  (rColor: RGBColor; VAR hColor: HSVColor);
  7789.  
  7790. Converting Between SmallFract and Fixed Values
  7791.  
  7792. FUNCTION SmallFract2Fix  (s: SmallFract): Fixed;
  7793. FUNCTION Fix2SmallFract  (f: Fixed): SmallFract;
  7794. _______________________________________________________________________________
  7795.  
  7796. æKY  Assembly…Language…Information…for…Color…Picker…Package
  7797. æC »Assembly Language Information                                     Color Picker Package
  7798. _______________________________________________________________________________
  7799.  
  7800. Constants
  7801.  
  7802. Fix2SmallFract  .EQU  1  ; selector for Fix2SmallFract
  7803. SmallFract2Fix  .EQU  2  ; selector for mallFract2Fix
  7804. CMY2RGB         .EQU  3  ; selector for CMY2RGB
  7805. RGB2CMY         .EQU  4  ; selector for RGB2CMY
  7806. HSL2RGB         .EQU  5  ; selector for HSL2RGB
  7807. RGB2HSL         .EQU  6  ; selector for RGB2HSL
  7808. HSV2RGB         .EQU  7  ; selector for HSV2RGB
  7809. RGB2HSV         .EQU  8  ; selector for RGB2HSV
  7810. GetColor        .EQU  9  ; selector for GetColor
  7811.  
  7812. Macro
  7813.   _Pack12
  7814. _______________________________________________________________________________
  7815.  
  7816.  
  7817. æKY ColorQuickDraw
  7818. æC 
  7819. _______________________________________________________________________________
  7820.  
  7821. COLOR QUICKDRAW
  7822. _______________________________________________________________________________
  7823.  
  7824. About…The…Color…Quickdraw…Chapter
  7825. About…Color…Quickdraw
  7826. Direct…Colors
  7827.     PixMap…Record…Extensions
  7828.     Direct…Pixel…Examples
  7829.     PICT…Extensions
  7830. Well-Behaved…Graphics…Applications
  7831. Using…Color…Quickdraw
  7832.     Copying…PixMap…Records
  7833.     Dithering
  7834.     Resizing…Images
  7835.     Luminance…Mapping
  7836.     Image…Resolution
  7837.     Importing…PixMap…Records
  7838.     Exporting…PixMap…Records
  7839.     Converting…a…Bitmap…to…a…Region
  7840.     Checking…that…QuickDraw…is…Done
  7841. New…Color…Quickdraw…Routines
  7842.     New…QuickDraw…Result…Codes
  7843.     Creating…an…Extended…PICT2…Picture
  7844.     From…Bitmap…to…Region
  7845.     Drawing…Completion
  7846.     Reporting…Data…Structure…Changes
  7847. The…Extended…PICT2…Format
  7848.     Sample…Extended…PICT2…File
  7849.     PICT2…Opcode…Types
  7850.     Extended…PICT2…Opcodes
  7851. Summary…of…Color…Quickdraw…Changes
  7852.     Color…Quickdraw…Constants
  7853.     Color…Quickdraw…Data…Types
  7854.     Color…Quickdraw…Routines
  7855.     Color…Quickdraw…Result…Codes
  7856. _______________________________________________________________________________
  7857.  
  7858.  
  7859.  
  7860. æKY About…The…Color…Quickdraw…Chapter
  7861. æC »ABOUT THIS CHAPTER                                                     Color QuickDraw
  7862. _______________________________________________________________________________
  7863.  
  7864. This chapter describes extensions to Color QuickDraw. You should be familiar
  7865. with the Graphics Overview in this volume, and with the Color QuickDraw
  7866. description in Inside Macintosh, Volume V. Developers of graphics cards and
  7867. drivers should also be familiar with the Slot Manager, Graphics Devices Manager,
  7868. and the Control Panel as described in both Inside Macintosh and and Developing
  7869. Cards and Drivers for the Macintosh Family, second edition.
  7870.  
  7871. This chapter describes extensions to the color facilities of Color QuickDraw,
  7872. and other new features, notably luminance mapping techniques and routines by
  7873. which existing applications can signal QuickDraw that a data structure has been
  7874. modified directly, rather than by use of QuickDraw routines.
  7875.  
  7876. If you use offscreen graphics to prepare images before copying them to the
  7877. screen, read the Graphics Devices Manager chapter in this volume for a
  7878. description of new routines that considerably reduce the complexity of that
  7879. task. 
  7880. _______________________________________________________________________________
  7881.  
  7882. æKY About…Color…Quickdraw
  7883. æC »ABOUT COLOR QUICKDRAW                                                  Color QuickDraw
  7884. _______________________________________________________________________________
  7885.  
  7886. Color QuickDraw now supports images that use direct, as well as indexed,
  7887. specification of colors.
  7888.  
  7889. Although an application specifies a color in terms of RGB space, the actual
  7890. value Color QuickDraw sends to the graphics card frame buffer (video RAM) is an
  7891. index value, which is used as input to the CLUT. An 8-bit index can specify 256
  7892. different entries (2 to the 8th power). On CLUT devices, the relationship
  7893. between the index value and the color generated depends on what colors are
  7894. currently stored where in the table.
  7895.  
  7896. At the cost of larger RAM requirements and, in some situations, slower
  7897. performance, direct color specification eliminates the need for table look-ups
  7898. and color searching algorithms, and lets your application directly specify over
  7899. 16 million colors. (For a comparison of the differences between indexed and
  7900. direct colors, see the Graphics Overview chapter.)
  7901.  
  7902. In addition to direct color, Color QuickDraw now also provides
  7903.  
  7904.   •   support for a true gray-scale display, providing better image fidelity on
  7905.       gray-scale devices
  7906.  
  7907.   •   a routine that converts a BitMap record into a region, which means you
  7908.       can, in effect, use region-manipulating routines on BitMap records
  7909.  
  7910.   •   four routines that enable you to signal Color QuickDraw when your
  7911.       application directly modifies a CLUT, PixPat, GrafPort, or GDevice data
  7912.       structure. (Direct modification is still discouraged.)
  7913.  
  7914.   •   a routine that creates and retrieves pictures with variable dots per inch
  7915.       resolution
  7916. _______________________________________________________________________________
  7917.  
  7918. æKY Direct…Colors
  7919. æC »DIRECT COLORS                                                          Color QuickDraw
  7920. _______________________________________________________________________________
  7921.  
  7922. Color QuickDraw now supports pixmaps with direct color specification as well as
  7923. the indexed method supported by the original release of Color QuickDraw. Since
  7924. QuickDraw has always striven to be device-independent, many applications need
  7925. make no changes. If your application specifies RGB colors, the system determines
  7926. the best colors for indexed devices and passes your RGB color to direct devices.
  7927.  
  7928. Changes to the Color QuickDraw interface affect only these two
  7929. color-specification data structures:
  7930.  
  7931.   •   the PixMap data structure that describes an image
  7932.  
  7933.   •   the PICT2 format in which images and graphics drawing operations are
  7934.       stored
  7935.  
  7936. Extensions to these two structures are described next.  
  7937. _______________________________________________________________________________
  7938.  
  7939. æKY PixMap…Record…Extensions
  7940. æC »PixMap Record Extensions                                               Color QuickDraw
  7941. _______________________________________________________________________________
  7942.  
  7943. Color QuickDraw supports two new pixel formats, corresponding to 16-bit and
  7944. 32-bit pixel depths. In both cases, the pixel’s displayed color is specified by
  7945. the pixel value; the pixel value is not an index into a CLUT. 
  7946.  
  7947. Note that the format of a PixMap record is not changed from that introduced with
  7948. the Macintosh II, but six PixMap fields can have new values. The PixMap data
  7949. structure is shown here, only the fields that can have new values are discussed.
  7950. See the Color QuickDraw chapter in Volume V for a complete PixMap description.
  7951.  
  7952. PixMap = RECORD
  7953. baseAddr:   Ptr;      {pointer to PixMap data}
  7954. rowBytes:   Integer;  {offset to next row} 
  7955. bounds:     Rect;     {boundary rectangle} 
  7956. pmVersion:  Integer;  {Color QuickDraw flags} 
  7957. packType:   Integer;  {packing format}
  7958. packSize:   Longint;  {size of data in packed state}
  7959. hRes:       Fixed;    {horizontal resolution}
  7960. vRes:       Fixed;    {vertical resolution}
  7961. pixelType:  Integer;  {format of pixel image}
  7962. pixelSize:  Integer;  {physical bits per pixel}
  7963. cmpCount:   Integer;  {logical components per pixel}
  7964. cmpSize:    Integer;  {logical bits per component}
  7965. planeBytes: Longint;  {offset to next plane}
  7966. pmTable:    CTabHandle; {absolute colors for this image}
  7967. pmReserved: Longint   {reserved for future expansion}
  7968. END;
  7969.  
  7970. Direct fields
  7971.  
  7972. rowBytes:  The restriction that rowbytes be less than $2000 has been relaxed:
  7973. rowbytes must be less than $4000. RowBytes must be even, and for best
  7974. performance it should be a multiple of 4.
  7975.   
  7976. pmVersion:  Normally 0. If pmVersion is 4, Color QuickDraw treats the pixmap’s
  7977. baseAddr as being 32-bit clean. This flag can be set by a new Graphics Devices
  7978. Manager routine, SetPMVersion. Most applications never need to set this field;
  7979. it is for low-level driver support.
  7980.  
  7981. pixelType:  Direct pixel values are specified by a pixelType field value of
  7982. RGBDirect, or 16. In a PixMap record of the gDevice record for a direct device,
  7983. the pixelType field will be set to the constant RGBDirect when the screen depth
  7984. is set.
  7985.  
  7986. pixelSize:  Pixel sizes must be a power of two. Color QuickDraw supports pixel
  7987. sizes of 1, 2, 4, and 8 bits; Color QuickDraw adds pixel sizes of 16 and 32
  7988. bits. 
  7989. cmpCount  
  7990.  
  7991. cmpCount:  With indexed pixels, each pixel is a single value representing an
  7992. index into a color table, and therefore the cmpCount field of a PixMap record is
  7993. 1—the index is the single component. With direct pixels, each pixel contains
  7994. three components, one integer each for the intensities of red, green, and blue,
  7995. and cmpCount is 3. Other values are undefined.
  7996.  
  7997. cmpSize:  The cmpSize field specifies the size of each component. A 32-bit pixel
  7998. consists of three components (red, green, and blue values) of 8 bits each. Since
  7999. cmpCount * cmpSize (3 * 8 = 24) is less than the value of pixelSize, 8 bits in
  8000. the pixel are not part of any component. These bits are unused: Color QuickDraw
  8001. sets them to zero in any image it creates, and if presented with a 32-bit image,
  8002. for example in CopyBits, it passes whatever bits are there. (Generally,
  8003. therefore, your application should clear image memory to 0 before creating a
  8004. 32-bit image.)
  8005.  
  8006. A 16-bit pixel consists of three components of 5 bits each. This leaves an
  8007. unused high-order bit, which QuickDraw sets to 0.
  8008.  
  8009. Color QuickDraw expects that the sizes of all components are the same, and that
  8010. cmpCount * cmpSize is less than or equal to pixelSize.
  8011.  
  8012. In each direct pixel, the pixel value is the concatenation of the red, green,
  8013. and blue components, where red is in the most significant bits and blue is in
  8014. the least significant. The entire direct pixel is right justified; unused bits
  8015. occupy the highest-order bits. 
  8016. _______________________________________________________________________________
  8017.  
  8018. æKY Direct…Pixel…Examples
  8019. æC »Direct Pixel Examples                                                  Color QuickDraw
  8020. _______________________________________________________________________________
  8021.  
  8022. Figure 16-1 shows a 32-bit direct pixel value, in which the pixel and component
  8023. fields have been set up as
  8024.  
  8025. pixelType  =  16;  {RGBDirect}
  8026. pixelSize  =  32;  {must be a power of 2}
  8027. cmpCount  =  3;    {red, green, and blue values}
  8028. cmpSize  =  8;     {8 bits for each component}
  8029.  
  8030. ø 16.1  A 32-bit direct pixel
  8031.  
  8032. In this example, the pixel value (hexadecimal) is $00178609, which deconstructs
  8033. into component values of $17 red, $86 green, and $09 blue, resulting in a medium
  8034. green. Figure 16-2 approximates the same color as in Figure 16-1 using a 16-bit
  8035. pixel specified as follows:
  8036.   
  8037. pixelType  =  16;  {RGBDirect}
  8038. pixelSize  =  16;  {Must be a power of 2}
  8039. cmpCount  =  3;    {red, green, and blue values}
  8040. cmpSize  =  5;     {5 bits for each component}
  8041.       
  8042. ø 16.2  A 16-bit direct pixel
  8043.  
  8044. Here the pixel value is $0A01, with component values of $02, $10, and $01 for
  8045. red, green and blue.
  8046.  
  8047. When converting a 32-bit pixel value to 16 bits, the three least significant
  8048. bits are dropped for each component. When converting a 16-bit pixel value to 32
  8049. bits, the most significant three bits of each component are replicated and added
  8050. to constitute the least significant three bits of the resulting 8-bit component,
  8051. as illustrated in Figure 16-3.
  8052.  
  8053. ø 16.3  Converting a 16-bit direct pixel to 32-bit direct
  8054.  
  8055. In this way, white stays white, black stays black, and other values are spread
  8056. appropriately.
  8057.  
  8058. Figures 16-4 to  16-9 show first how Color QuickDraw converts a full 48-bit RGB
  8059. color to 32, 16, and 8 bit values (the latter indexed), and then the reverse
  8060. process, of converting those values back to 48 bits.
  8061.  
  8062. ø 16.4  Converting a 48-bit RGB value to 32-bit direct
  8063.  
  8064. A 32-bit direct pixel uses the most significant 8 bits of each component, and
  8065. has an 8-bit pad.
  8066.  
  8067. ø 16.5  Converting a 48-bit RGB value to 16-bit direct
  8068.  
  8069. A 16-bit direct pixel uses the most significant 5 bits of each component, and
  8070. has a 1-bit pad.
  8071.  
  8072. ø 16.6  Converting a 48-bit value to an 8 bit index
  8073.  
  8074. To obtain an 8-bit pixel value, the Color Manager determines the closest RGB
  8075. value in the CLUT; its index value is stored in the 8-bit pixel. In the standard
  8076. 8-bit CLUT, from 'CLUT' resource with ID of 8, the nearest value to the original
  8077. RGB value of Figure 16-4 is in table entry 161. Note that with indexed pixels,
  8078. the pixel value has no direct relation to the original RGB value.
  8079.  
  8080. ø 16.7  Converting an 32-bit  pixel to 48 bits
  8081.  
  8082. Color QuickDraw expands a 32-bit pixel into a 48-bit value by dropping the pad
  8083. byte and doubling each 8-bit component.  Note that the resulting 48-bit value
  8084. differs (in the least significant 8 bits of each component) from the original in
  8085. Figure 16-4.
  8086.  
  8087. ø 16.8  Converting an 16-bit  pixel to 48 bits
  8088.  
  8089. Color QuickDraw expands a 16-bit pixel into a 48-bit value by dropping the pad
  8090. bit and inserting three copies of each 5-bit component and a copy of the most
  8091. significant bit into each 16-bit component of the destination. Note that the
  8092. result differs (in the least significant 11 bits of each component) from the
  8093. original value.
  8094.  
  8095. ø 16.9  Converting an 8-bit  indexed pixel to 48 bits
  8096.  
  8097. Color QuickDraw expands an 8-bit indexed pixel into a 48-bit value by taking the
  8098. 48-bit value pointed to in the CLUT. The difference between this value and the
  8099. original 48-bit value varies, depending on the CLUT values.
  8100.  
  8101. _______________________________________________________________________________
  8102.  
  8103. æKY PICT…Extensions
  8104. æC »PICT Extensions                                                        Color QuickDraw
  8105. _______________________________________________________________________________
  8106.  
  8107. The PICT2 picture format defined for Color QuickDraw only supports images
  8108. consisting of CLUT indices. The PICT2 format has been expanded so that it can
  8109. record images with pixels that directly specify a given color.
  8110.  
  8111. To the current imaging opcodes BitsRect, BitsRgn, PackBitsRect, and PackBitsRgn,
  8112. Color QuickDraw adds DirectBitsRect and DirectBitsRgn. These opcodes enable your
  8113. application to cut, paste, and store images with up to 32 bits of color
  8114. information per pixel.
  8115.  
  8116. A new routine, the OpenCPicture function, lets your application create a PICT2
  8117. file and pass rectangle and resolution information, which is stored in the PICT2
  8118. header. This provides a simple mechanism for creating images with spatial
  8119. resolution other than 72 dpi. The OpenCPicture function is described in “New
  8120. Color QuickDraw Routines” later in this chapter.
  8121.  
  8122. The following opcodes occur only in pictures using the extended PICT2 format.
  8123. Two new opcodes specify direct pixels: 
  8124.  
  8125. DirectBitsRect  EQU  $9A    ; direct data copybits, rect clipped
  8126. DirectBitsRgn   EQU  $9B    ; direct data copybits, rgn clipped 
  8127.  
  8128. In addition, an opcode has been defined to specify font information:
  8129.  
  8130. FontName        EQU    $2C    ; font ID and name
  8131.  
  8132. The PICT2 format is described fully in “The Extended PICT2 Format.”
  8133. _______________________________________________________________________________
  8134.  
  8135. æKY Well-Behaved…Graphics…Applications
  8136. æC »WELL-BEHAVED GRAPHICS APPLICATIONS                                     Color QuickDraw
  8137. _______________________________________________________________________________
  8138.  
  8139. Over the years, some developers have written applications that modify the
  8140. QuickDraw data structures directly rather than using the routines provided for
  8141. that purpose. Then, when Apple engineers improve QuickDraw, the applications
  8142. break.  
  8143.  
  8144. As both QuickDraw and graphics applications grow more complex, the problem
  8145. becomes acute. This section points to new routines you can use to signal
  8146. QuickDraw when your application modifies certain data structures directly so
  8147. that QuickDraw can take note and act accordingly. 
  8148.  
  8149. Applications should not directly change fields in QuickDraw data structures, but
  8150. use the following procedures instead:
  8151.  
  8152.  
  8153. AddComp        AddSearch           BackColor
  8154. BackPat        BackPixPat          CharExtra
  8155. ClipRect       ColorBit            CopyPixPat
  8156. DelComp        DelSearch           ForeColor
  8157. GrafDevice     HideCursor          HidePen
  8158. HiliteColor    MakeRGBPat          Move
  8159. MovePortTo     MoveTo              ObscureCursor
  8160. OpColor        PenMode             PenNormal
  8161. PenPat         PenPixPat           PenSize
  8162. PortSize       RGBBackColor        RGBForeColor
  8163. SetCCursor     SetClientID         SetClip
  8164. SetCursor      SetDeviceAttribute  SetGDevice
  8165. SetOrigin      SetPenState         SetPort
  8166. SetPortBits    SetPortPix          ShowCursor
  8167. ShowPen        SpaceExtra          TextFace
  8168. TextFont       TextMode            TextSize
  8169.  
  8170. Using these routines rather than directly modifying the data structures ensures
  8171. that your application will fully benefit from any future improvements to
  8172. QuickDraw. In particular, the OffscreenGWorld routines described in the Graphics
  8173. Devices Manager chapter of this volume remove much of the need for directly
  8174. modifying graphics data structures.
  8175.  
  8176. Apple strongly recommends that new applications follow these guidelines.  
  8177. However, it is possible to make existing applications better-behaved by calling
  8178. one of the following procedures after directly changing a QuickDraw data
  8179. structure and before making any other QuickDraw call:
  8180.  
  8181.   CTabChanged 
  8182.   PixPatChanged 
  8183.   PortChanged
  8184.   GDeviceChanged
  8185.  
  8186. These routines inform QuickDraw that a direct modification has occurred so it
  8187. can update its world. They are described in the “New Color QuickDraw
  8188. Routines”section.
  8189.  
  8190. _______________________________________________________________________________
  8191.  
  8192. æKY Using…Color…Quickdraw
  8193. æC »USING COLOR QUICKDRAW                                                  Color QuickDraw
  8194. _______________________________________________________________________________
  8195.  
  8196. If your application uses color in straightforward ways it will probably execute
  8197. without change in a direct pixel environment. 
  8198.  
  8199. For most other applications, the main concern is in the creation and use of
  8200. special-purpose PixMap and GDevice records—and by using the OffscreenGWorld
  8201. routines described in the Graphics Devices Manager chapter you will find such
  8202. tasks far easier than before. 
  8203.  
  8204. If you must work with GrafPort, PixMap, and GDevice records in ways beyond the
  8205. scope of the OffscreenGWorld routines, the following guidelines may aid you in
  8206. adapting to Color QuickDraw’s direct pixel environment:
  8207.  
  8208.   •   Don’t draw directly to the screen. A screen baseAddr is only guaranteed
  8209.       to be a valid pointer in 32-bit addressing mode.
  8210.  
  8211.   •   Don’t directly change the fgColor or bkColor fields of a grafPort and
  8212.       expect them to be used as the pixel values. Color QuickDraw recalculates
  8213.       these values for each device. If you really want to draw in an index
  8214.       instead of a color, use a palette with pmExplicit colors, as described in
  8215.       the Palette Manager chapter in this volume. For device independant colors
  8216.       use the RGBForeColor and RGBBackColor procedures.
  8217.  
  8218.   •   Fill out all the fields in a new PixMap record. The NewPixMap function
  8219.       returns a PixMap record that has been cloned from TheGDevice record’s
  8220.       PixMap record. If you don’t want a copy of the main screen’s PixMap
  8221.       record—for example, you want one that is a different depth—then you must
  8222.       fill out more fields than just pixelSize: you must fill out the
  8223.       pixelType, cmpCount, and cmpSize fields. Set pmVersion to 0 when
  8224.       initializing your own PixMap record. For future compatibility you should
  8225.       also set packType, packSize, planeBytes, and pmReserved to 0.
  8226.  
  8227.   •   Don’t clone a graphic device record’s PixMap record. Instead, use the
  8228.       NewPixmap function or the CopyPixMap procedure. If you must create or
  8229.       manually clone a PixMap record, make sure to set the pmVersion field and
  8230.       other unused fields to 0 for future compatibility.
  8231.  
  8232.   •   Fill out all the fields of a new GDevice. When creating an offscreen
  8233.       graphic device record by calling NewGDevice with a mode of -1, you must
  8234.       fill out the fields of the graphic device record (for instance, gdType)
  8235.       yourself. If you want a copy of an existing graphic device record, then
  8236.       copy the gdType field from it. If you explicitly want an indexed device
  8237.       then, set gdType to 0.
  8238.   •   Don’t assume a PixMap record has a CLUT. Direct PixMap records need not
  8239.       have CLUTs. For compatibility, direct PixMap records should have dummy
  8240.       pmTable handles that point to color table headers with seed values equal
  8241.       to cmpSize * cmpCnt, and the ctSize field should be set to 0.
  8242.  
  8243. Again, all these problems are eased if you use the OffscreenGWorld routines.
  8244.  
  8245. _______________________________________________________________________________
  8246.  
  8247. æKY Copying…PixMap…Records
  8248. æC »Copying PixMap Records                                                 Color QuickDraw
  8249. _______________________________________________________________________________
  8250.  
  8251. PixMap records are copied using the current GDevice record (pointed to by the
  8252. TheGDevice global variable) to determine the destination color information.
  8253. Consequently, whenever copying to an offscreen PixMap record with
  8254. characteristics differing from those of the current GDevice record (which is
  8255. usually the main screen), you should create an appropriate offscreen graphic
  8256. device record and set it as the current graphic device record before the copy.
  8257. If an offscreen PixMap record is only copied from, then no offscreen graphic
  8258. device record is needed since Color QuickDraw obtains the source color
  8259. information from the source PixMap record. (See the Graphic Devices Manager
  8260. chapter for information about offscreen graphics routines and data structures.)
  8261. _______________________________________________________________________________
  8262.  
  8263. æKY Dithering
  8264. æC »Dithering                                                              Color QuickDraw
  8265. _______________________________________________________________________________
  8266.  
  8267. The CopyBits procedure now provides a new dither copy mode.
  8268.  
  8269. Copying using CopyBits from any PixMap record to an indexed device works in one
  8270. of two ways:  
  8271.  
  8272.   •   If the transfer mode is DitherCopy, then CopyBits does its best to
  8273.       provide error diffusion during the copy operation. As with arithmetic
  8274.       transfer modes, hidden colors are ignored, so that color matching is
  8275.       limited by the resolution of the inverse table for the destination
  8276.       graphics device. (See the discussion of hidden colors in the Inverse
  8277.       Table section of the Color Manager chapter, Inside Macintosh, Volume V.)
  8278.       DitherCopy provides good results for most images, but does have
  8279.       drawbacks. A clipped DitherCopy does not provide pixel-for-pixel
  8280.       equivalence to the same unclipped DitherCopy—thus updates are not
  8281.       equivalent to saving the bits behind, and clipped XOR copies will not
  8282.       perform as erases.
  8283.  
  8284.       Currently, if a color search procedure is present, copy mode is used     
  8285.  
  8286.       instead of dither mode. (This may change in future versions.) 
  8287.  
  8288.   •   If you copy from any PixMap record to an indexed device using the classic
  8289.       copy mode, color mapping is done on a pixel-by-pixel basis—no errors are
  8290.       accumulated and hidden colors are ignored. If a color search procedure is
  8291.       present, it is called on a pixel-by-pixel basis.
  8292.  
  8293. If you copy from any PixMap record to a direct device, dithering is never done,
  8294. since dithering is generally useful only when copying to a destination with a
  8295. lower color resolution than the source. If the destination device is 16-bits or
  8296. 32-bits per pixel, then no error diffusion is performed. You can use dithering
  8297. when copying between indexed PixMap records, such as from an 8-bit pixel depth
  8298. to a 4-bit depth, or between two 8-bit PixMap records with different color
  8299. tables.
  8300.  
  8301. _______________________________________________________________________________
  8302.  
  8303. æKY Resizing…Images
  8304. æC »Resizing Images                                                        Color QuickDraw
  8305. _______________________________________________________________________________
  8306.  
  8307. When copying from direct pixel maps, if the destination rectangle is smaller
  8308. than the source rectangle, Color QuickDraw uses an averaging technique to
  8309. provide destination pixels, maintaining high-quality images when shrinking.
  8310. Pixel averaging is also performed when shrinking indexed images using dither
  8311. copy modes, regardless of the destination.
  8312.  
  8313. _______________________________________________________________________________
  8314.  
  8315. æKY Luminance…Mapping
  8316. æC »Luminance Mapping                                                      Color QuickDraw
  8317. _______________________________________________________________________________
  8318.  
  8319. When the user sets a screen device to a gray-scale mode, Color QuickDraw places
  8320. an evenly spaced set of grays in the device CLUT such that they form a linear
  8321. ramp from white to black. 
  8322.  
  8323. When Color QuickDraw displays a color on a graphics device whose pmTable
  8324. contains only grays (ignoring entries used for animation), it computes the
  8325. luminance of the desired color and uses that to determine the appropriate gray
  8326. value to draw.
  8327.  
  8328. To facilitate the creation of grayscale devices, the GetCTable function has been
  8329. enhanced to recognize additional standard CLUT IDs. As described in Volume V,
  8330. the GetCTable function looks like this:
  8331.  
  8332. FUNCTION GetCTable (ctID: Integer) : CTabHandle;
  8333.  
  8334. The default grayscale CLUT for a given pixel depth can be obtained by calling
  8335. GetCTable with a ctID value of PixelSize +32.
  8336.  
  8337. PixelSize    CLUT ID  Color Table Composition         
  8338.         2         34  black, white, 33% gray, 66% gray
  8339.         4         36  black, 14 shades of gray, white
  8340.         8         40  black, 254 shades of gray, white
  8341.  
  8342. The equivalent default color tables can be obtained by adding 64 to the bit
  8343. depth, as described in the Palette Manager chapter.
  8344.  
  8345. PixelSize  CLUT ID  Color Table Composition         
  8346.         2       66  black, white, 50% gray, highlight 
  8347.         4       68  black, 14 colors including a highlight, white
  8348.         8       72  black, 254 colors including a highlight, white
  8349. _______________________________________________________________________________
  8350.  
  8351. æKY Image…Resolution
  8352. æC »Image Resolution                                                       Color QuickDraw
  8353. _______________________________________________________________________________
  8354.  
  8355. Color QuickDraw supports pixel maps of resolutions other than 72 dots per inch 
  8356. (dpi). In the past, applications have accepted pixel maps of a certain number of
  8357. rows and columns and assumed that they were generated on a 72 dpi device. Such
  8358. pixel maps were usually copied and printed at a 72 dpi resolution, lending the
  8359. impression that QuickDraw could not handle pixel maps of higher density. 
  8360.  
  8361. With the advent of frame grabbers and scanners, many pixel maps have resolutions
  8362. of 150, 200, 300 dpi, or greater. A user expects pixel maps to display an
  8363. approximation of the information on a 72 dpi display but print on a higher
  8364. resolution device to the best of the device's ability.
  8365.  
  8366. _______________________________________________________________________________
  8367.  
  8368. æKY Importing…PixMap…Records
  8369. æC »Importing PixMap Records                                               Color QuickDraw
  8370. _______________________________________________________________________________
  8371.  
  8372. The resolution of a PixMap record is contained in the hRes and vRes fields.
  8373. These values are fixed point numbers in dots per inch. When importing pictures,
  8374. applications should check the picture type to see if it was created with
  8375. OpenCPicture.
  8376.  
  8377. An alternative is to replace the StdBits bottleneck during playback. When the
  8378. bottleneck procedure is called, you should
  8379.  
  8380. 1.  check to guarantee that the source is a PixMap record by checking the high
  8381. bit of the PMVersion(rowBytes) field
  8382.  
  8383. 2.  read the hRes and vRes information out of the source PixMap record
  8384.  
  8385. At this point, the source rect field indicates the size of the source in pixels
  8386. at the resolution specified by the hRes and vRes fields. To display it at
  8387. another resolution, your application should compute the dest rect field value
  8388. appropriately. For example if the source resolution is 300 dpi and the intention
  8389. is to display it at 75 dpi, then the destination rectangle width and height
  8390. should be computed as 1/4 of that of the source.  
  8391. _______________________________________________________________________________
  8392.  
  8393. æKY Exporting…PixMap…Records
  8394. æC »Exporting PixMap Records                                               Color QuickDraw
  8395. _______________________________________________________________________________
  8396.  
  8397. When exporting PixMap records, your application should ensure that the hRes and
  8398. vRes fields accurately reflect the image data. During picture recording, the
  8399. destination rectangle of the CopyBits call should be appropriate for display at
  8400. 72 dpi. If you want an entire picture to be a different resolution, use the
  8401. OpenCPicture function.
  8402.  
  8403. _______________________________________________________________________________
  8404.  
  8405. æKY Converting…a…Bitmap…to…a…Region
  8406. æC »Converting a Bitmap to a Region                                        Color QuickDraw
  8407. _______________________________________________________________________________
  8408.  
  8409. A new function, BitMapToRegion, converts a bitmap to a region. If you used the
  8410. PaintRgn procedure on the converted region, the resulting region would be the
  8411. same as the bitmap. This procedure may be useful if you want to test the mouse
  8412. for hits against the black pixels in a bitmap, or drag the outline of a bitmap
  8413. using DragGrayRegion.  
  8414. _______________________________________________________________________________
  8415.  
  8416. æKY Checking…that…QuickDraw…is…Done
  8417. æC »Checking that QuickDraw is Done                                        Color QuickDraw
  8418. _______________________________________________________________________________
  8419.  
  8420. A new function, QDDone, checks to see whether QuickDraw drawing operations have
  8421. completed in a grafport.  This is useful if you are executing in an environment
  8422. with a graphics accelerator, where drawing operations may proceed
  8423. asynchronously.  
  8424.  
  8425. _______________________________________________________________________________
  8426.  
  8427. æKY New…Color…Quickdraw…Routines
  8428. æC »NEW COLOR QUICKDRAW ROUTINES                                           Color QuickDraw
  8429. _______________________________________________________________________________
  8430.  
  8431. Since using direct color only requires internal Color QuickDraw changes to
  8432. recognize direct pixel values, no new routines are defined for direct color. 
  8433. _______________________________________________________________________________
  8434.  
  8435. æKY New…QuickDraw…Result…Codes
  8436. æC »New QuickDraw Result Codes                                             Color QuickDraw
  8437. _______________________________________________________________________________
  8438.  
  8439. QuickDraw uses stack space for work buffers. For complex operations such as
  8440. depth conversion, dithering, or image resizing, stack space may not be
  8441. sufficient. Color QuickDraw now attempts to get temporary memory from
  8442. MultiFinder. If that is still not enough, or if MultiFinder is not present,
  8443. Color QuickDraw returns
  8444.  
  8445.   QDErr  -149  Insufficient stack
  8446.  
  8447. One recourse for the application is to divide the operation—for example divide
  8448. the image into left and right halves—and try again. An alternative is to make
  8449. the stack larger.
  8450.  
  8451. While recording drawing operations into an open region the resulting region
  8452. description might overflow the 64 KB limit. Should this happen Color QuickDraw
  8453. will return -147 in QDErr:
  8454.  
  8455.   QDErr  -147  Region too big
  8456.  
  8457. Since the resulting region is potentially corrupt, closeRgn returns an empty
  8458. region if it detects QDErr has been set to -147.
  8459.  
  8460. _______________________________________________________________________________
  8461.  
  8462. æKY Creating…an…Extended…PICT2…Picture
  8463. æC »Creating an Extended PICT2 Picture                                     Color QuickDraw
  8464. _______________________________________________________________________________
  8465.  
  8466. FUNCTION OpenCPicture (newHeader: PICT2Header) : PicHandle;
  8467.  
  8468. OpenCPicture performs the same functions as OpenPicture, except that it creates
  8469. an extended PICT2 format file, with pixel resolution and the best imaging
  8470. rectangle stored in the header.
  8471.  
  8472. You pass a PICT2Header record describing the rectangle that encloses the drawing
  8473. information you supply for the picture, and you pass horizontal and vertical
  8474. resolutions describing the best resolution for displaying the picture in the
  8475. rectangle. The structure of a PICT2Header record is
  8476.  
  8477. PICT2Header = 
  8478. RECORD
  8479.   SrcRect:  Rect    {source rectangle for best display}
  8480.                     {at HRes, VRes resolution}
  8481.   hRes:     Fixed;  {best horizontal resolution}
  8482.   vRes:     Fixed;  {best vertical resolution}
  8483.   version:  word;   {set to -2}
  8484.   reserved: word;   {reserved for future use}
  8485.   END;
  8486.  
  8487. Note that the order the information is recorded in the PICT2 header differs from
  8488. the order in this record.  See the sample PICT2 file in “The Extended PICT2
  8489. Format.” 
  8490.  
  8491. As with OpenPicture, you close the picture using ClosePicture, and draw it using
  8492. DrawPicture.
  8493.  
  8494. _______________________________________________________________________________
  8495.  
  8496. æKY From…Bitmap…to…Region
  8497. æC »From Bitmap to Region                                                  Color QuickDraw
  8498. _______________________________________________________________________________
  8499.  
  8500. FUNCTION BitMapToRegion (region:RGNHandle; bMap:BitMap) : OSErr;
  8501.  
  8502. The region parameter must be a valid region handle created with a NewRgn
  8503. function. The old region contents are lost.
  8504.  
  8505. The bMap parameter may either be a BitMap or PixMap record. If a PixMap record
  8506. is passed, its pixel size (bits per pixel) must be 1. 
  8507.  
  8508. Result codes
  8509.     rgnTooBigErr   -500  BitMap would convert into a region greater 
  8510.                          than 32 KB 
  8511. pixmapTooDeepErr   -148  PixMap record is deeper than 1 bit per pixel
  8512. _______________________________________________________________________________
  8513.  
  8514. æKY Drawing…Completion
  8515. æC »Drawing Completion                                                     Color QuickDraw
  8516. _______________________________________________________________________________
  8517.  
  8518. FUNCTION QDDone (port:GrafPtr) : Boolean;
  8519.  
  8520. The QDDone function returns true if drawing operations have completed in the
  8521. designated port, false if any remain to be executed.  This call may be useful if
  8522. a graphics accelerator is present and operating asynchronously.  You can ensure
  8523. that all drawing has been done and avoid the possibility that new drawing
  8524. operations might be overlaid by previously issued but unexecuted operations.
  8525.  
  8526. _______________________________________________________________________________
  8527.  
  8528. æKY Reporting…Data…Structure…Changes
  8529. æC »Reporting Data Structure Changes                                       Color QuickDraw
  8530. _______________________________________________________________________________
  8531.  
  8532. The following routines can be used to mitigate possible side effects of directly
  8533. changing a CLUT, PixPat, GrafPort, or GDevice data structure.
  8534.  
  8535. PROCEDURE CTabChanged (ctab: CTabHandle);
  8536.  
  8537. Call CTabChanged after modifying the content of a color table. CTabChanged calls
  8538. GetCTSeed to get a new seed for the color table and notifies QuickDraw of the
  8539. change.
  8540.  
  8541. PROCEDURE PixPatChanged (ppat: PixPatHandle);
  8542.  
  8543. Call PixPatChanged after modifying a PixPat data structure or any of its
  8544. substructures (patMap or patData records). PixPatChanged sets the patXValid flag
  8545. to -1 and notifies QuickDraw of the change.
  8546.  
  8547. If your application changes the pmTable field of the pixel pattern’s patMap, it
  8548. should call PixPatChanged. However, if your application changes the content of
  8549. the CLUT referenced by pmTable, it should call CTabChanged as well.
  8550.  
  8551. PROCEDURE PortChanged (port: GrafPtr);
  8552.  
  8553. Call PortChanged after modifying the content of a port or any of its
  8554. substructures. PortChanged notifies QuickDraw of the change.
  8555.  
  8556. None of the PixPat records pointed to by a CGrafPort record should be changed
  8557. directly. Use PenPixPat and BackPixPat instead. However, if your application
  8558. changes the content of one of the PixPat records, it should call PixPatChanged.
  8559.  
  8560. If your application changes the pmTable field of the port’s PixMap, it should
  8561. call PortChanged. However, if your application changes the content of the color
  8562. table referenced by pmTable, it should call CTabChanged as well.
  8563.  
  8564. PROCEDURE GDeviceChanged (gdh: GDHandle);
  8565.  
  8566. Call GDeviceChanged after modifying a gDevice graphics device record or any of
  8567. its substructures. GDeviceChanged notifies QuickDraw of the change.
  8568.  
  8569. If your application changes the pmTable field of the graphics device record’s
  8570. PixMap, it should call GDeviceChanged. However, if your application changes the
  8571. content of the color table referenced by gdPMap, it should call CTabChanged as
  8572. well.
  8573.  
  8574. _______________________________________________________________________________
  8575.  
  8576. æKY The…Extended…PICT2…Format
  8577. æC »THE EXTENDED PICT2 FORMAT                                              Color QuickDraw
  8578. _______________________________________________________________________________
  8579.  
  8580. The PICT2 format presented in the Color QuickDraw chapter of Volume V has been
  8581. extended to allow storing direct PixMaps and for maintaining resolution and
  8582. imaging rectangle information.
  8583.  
  8584.  
  8585. The major differences between version 1 and version 2 pictures are that three
  8586. opcodes previously listed as reserved have been defined, and one defined opcode
  8587. has been redefined:
  8588.  
  8589. Opcode 2C signals font name information.
  8590.  
  8591. Opcodes 9A and 9B now define direct-pixel pictures, with PixMaps containing
  8592. three components, directly specifying RGB values.
  8593.  
  8594. Opcode 0C00 still signifies a header record, and it is still 24 bytes, but the
  8595. contents have changed.
  8596.  
  8597. This section presents a sample PICT file and the extended PICT2 opcodes.
  8598.  
  8599. _______________________________________________________________________________
  8600.  
  8601. æKY Sample…Extended…PICT2…File
  8602. æC »Sample Extended PICT2 File                                             Color QuickDraw
  8603. _______________________________________________________________________________
  8604.  
  8605. An example of an extended PICT2 data file that can display a single direct-pixel
  8606. image is shown in Table 1.
  8607.  
  8608. Table 1. PICT file example
  8609. ________________________________________________________________________
  8610.   Size  Name    Description
  8611.   (in bytes)
  8612.   2  picSize    low word of picture size
  8613.   8  picFrame   rectangular bounding box of picture, at 
  8614.                 72 dpi
  8615.  
  8616. Picture Definition Data:
  8617.  
  8618.   2  version op  version opcode = $0011
  8619.   2  version     version number = $02FF
  8620.   2  Header op   header opcode = $0C00
  8621.   2  version     set to -2 for extended PICT2
  8622.   2  reserved    reserved for future Apple use
  8623.   4  HRes        native horizontal resolution 
  8624.   4  VRes        native vertical resolution 
  8625.   8  SrcRect     native source rectangle
  8626.   4  reserved    reserved for future Apple use
  8627.   2  opbitsRect  bitMap opcode = $009A for direct
  8628.   4  baseAddr    for direct must be $000000FF. See Table 4  
  8629.   2  rowBytes    integer, must have high bit set to signal pixMap
  8630.   8  bounds      rectangle, bounding rectangle at source resolution
  8631.   2  pmVersion   integer, pixMap version number = 0
  8632.   2  packType    integer, defines packing format
  8633.   4  packSize    LongInt, length of pixel data = 0
  8634.   4  hRes        fixed, horizontal resolution (dpi) of source data, 
  8635.                  normally $00480000 (72 dpi)
  8636.   4  vRes        fixed, vertical resolution (dpi) of source data,
  8637.                  normally $00480000 (72 dpi)
  8638.   2  pixelType   integer, defines pixel type; 16 for direct
  8639.   2  pixelSize   integer, number of bits in pixel; 16 or 32 for direct
  8640.   2  cmpCount    integer, number of components in pixel; 3 for direct
  8641.   2  cmpSize     integer, number of bits per component; 5 or 8 for direct
  8642.   4  planeBytes  LongInt, offset to next plane = 0
  8643.      pmTable     color table = 0
  8644.      pmReserved  reserved = 0
  8645.   4  ctSeed      LongInt, color table seed
  8646.   2  ctFlags     integer, flags for color table
  8647.   2  ctSize      integer, number of entries in ctTable –1
  8648.   (ctSize+1) *  8   ctTable  color lookup table data
  8649.   8  srcRect     rectangle, source rectangle at source resolution
  8650.   8  dstRect     rectangle, destination rectangle at 72 dpi resolution 
  8651.   2  mode        integer, transfer mode see Table 5    
  8652.      pixData     pixel data  
  8653.   2  endPICT op  end-of-picture opcode = $00FF
  8654.  
  8655. _______________________________________________________________________________
  8656.  
  8657. æKY PICT2…Opcode…Types
  8658. æC »PICT2 Opcode Types                                                     Color QuickDraw
  8659. _______________________________________________________________________________
  8660.  
  8661. The following description shows the new PICT2 format, with changes from the
  8662. description in Volume V indicated by an asterisk.
  8663.  
  8664.  
  8665. The opcode information in Table 3x is provided for the purpose of debugging
  8666. application-generated PICT files. Your application should generate and read PICT
  8667. files only by using standard QuickDraw or Color QuickDraw routines (OpenPicture,
  8668. OpenCPicture, ClosePicture).  The data types listed in Table 2x are used in the
  8669. Table 3x opcode definitions. 
  8670.  
  8671. Table 2.  Data types
  8672. ________________________________________________________________________
  8673. Type          Size
  8674. v1 opcode     1 byte
  8675. v2 opcode     2 bytes
  8676. integer       2 bytes
  8677. long integer  4 bytes
  8678. mode          2 bytes
  8679. point         4 bytes
  8680. 0..255        1 byte
  8681. –128..127     1 byte (signed)
  8682. rect          8 bytes (top, left, bottom, right: integer)
  8683. poly         10+ bytes
  8684. region       10+ bytes
  8685. fixed-point number  4 bytes
  8686. pattern       8 bytes
  8687. rowbytes      2 bytes (always an even quantity)
  8688. ________________________________________________________________________
  8689.  
  8690. _______________________________________________________________________________
  8691.  
  8692. æKY Extended…PICT2…Opcodes
  8693. æC »Extended PICT2 Opcodes                                                 Color QuickDraw
  8694. _______________________________________________________________________________
  8695.  
  8696. Valid picture opcodes are listed in Table 3.  New opcodes or those altered to
  8697. extend the PICT2 format are indicated by a leading asterisk (*). The unused
  8698. opcodes found throughout the table are reserved for Apple use. The length of the
  8699. data that follows these opcodes is pre-defined, so if they are encountered in
  8700. pictures, they can simply be skipped. By default, QuickDraw reads and then
  8701. ignores these opcodes.
  8702.  
  8703.  
  8704.  
  8705. Table 3.  PICT opcodes
  8706. ________________________________________________________________________
  8707. Opcode Name            Description                           Data Size
  8708.                                                              (in bytes)
  8709. $0000  NOP             nop                                   0
  8710. $0001  Clip            clip                                  region size + data
  8711. $0002  BkPat           background pattern                    8
  8712. $0003  TxFont          text font (word)                      2
  8713. $0004  TxFace          text face (byte)                      1
  8714. $0005  TxMode          text mode (word)                      2
  8715. $0006  SpExtra         space extra (fixed point)             4
  8716. $0007  PnSize          pen size (point)                      4
  8717. $0008  PnMode          pen mode (word)                       2
  8718. $0009  PnPat           pen pattern                           8
  8719. $000A  FillPat         fill pattern                          8
  8720. $000B  OvSize          oval size (point)                     4
  8721. $000C  Origin          dh, dv (word)                         4
  8722. $000D  TxSize          text size (word)                      2
  8723. $000E  FgColor         foreground color (long)               4
  8724. $000F  BkColor         background color (long)               4
  8725. $0010  TxRatio         numer (point), denom (point)          8
  8726. $0011  Version         version (byte)                        1
  8727. $0012  BkPixPat        color background pattern              variable:
  8728.                                                              see Table 4
  8729. $0013  PnPixPat        color pen pattern                     variable:
  8730.                                                              see Table 4
  8731. $0014  FillPixPat      color fill pattern                    variable:
  8732.                                                              see Table 4
  8733. $0015  PnLocHFrac      fractional pen position               2
  8734. $0016  ChExtra         extra for each character              2
  8735. $0017  reserved        opcode                                0
  8736. $0018  reserved        opcode                                0
  8737. $0019  reserved        opcode                                0
  8738. $001A  RGBFgCol        RGB foreColor                         variable:
  8739.                                                              see Table 4
  8740. $001B  RGBBkCol        RGB backColor                         variable:
  8741.                                                              see Table 4
  8742. $001C  HiliteMode      hilite mode flag                      0
  8743. $001D  HiliteColor     RGB hilite color                      variable:
  8744.                                                              see Table 4
  8745. $001E  DefHilite       Use default hilite color              0
  8746. $001F  OpColor         RGB OpColor for                       variable:
  8747.                        arithmetic modes                      see Table 4
  8748. $0020  Line            pnLoc (point), newPt (point)          8
  8749. $0021  LineFrom        newPt (point)                         4
  8750. $0022  ShortLine       pnLoc (point, dh, dv                  6
  8751.                        (-128..127)
  8752. $0023  ShortLineFrom   dh, dv (-128..127)                    2
  8753. $0024  reserved        opcode + 2 bytes data                 2+ data
  8754.                        length + data                         length
  8755. $0025  reserved        opcode + 2 bytes data                 2+ data
  8756.                        length + data                         length       
  8757. $0026  reserved        opcode + 2 bytes data                 2+ data
  8758.                        length + data                         length
  8759. $0027  reserved        opcode + 2 bytes data                 2+ data
  8760.                        length + data                         length
  8761. $0028  LongText        txLoc (point), count                  5 + text
  8762.                        (0..255), text
  8763. $0029  DHText          dh (0..255), count                    2 + text
  8764.                        (0..255), text
  8765. $002A  DVText          dv (0..255), count                    2 + text
  8766.                        (0..255), text
  8767. $002B  DHDVText        dh, dv (0..255), count                3 + text
  8768.                        (0..255), text
  8769. $002C  *fontName       data length (word), old font          5+ name
  8770.                        ID (word), name length (byte),        length
  8771.                        font name 
  8772. $002D  reserved        opcode + 2 bytes data                 2+ data    
  8773.                        length + data                         length
  8774. $002E  reserved        opcode + 2 bytes data                 2+ data
  8775.                        length + data                         length
  8776. $002F  reserved        opcode + 2 bytes data                 2+ data
  8777.                        length + datalength
  8778. $0030  frameRect       rect                                  8
  8779. $0031  paintRect       rect                                  8
  8780. $0032  eraseRect       rect                                  8
  8781. $0033  invertRect      rect                                  8
  8782. $0034  fillRect        rect                                  8
  8783. $0035  reserved        opcode + 8 bytes data                 8
  8784. $0036  reserved        opcode + 8 bytes data                 8
  8785. $0037  reserved        opcode + 8 bytes data                 8
  8786. $0038  frameSameRect   rect                                  0
  8787. $0039  paintSameRect   rect                                  0
  8788. $003A  eraseSameRect   rect                                  0
  8789. $003B  invertSameRect  rect                                  0
  8790. $003C  fillSameRect    rectangle                             0
  8791. $003D  reserved        opcode                                0
  8792. $003E  reserved        opcode                                0
  8793. $003F  reserved        opcode                                0
  8794. $0040  frameRRect      rect (see Note # 5 )                  8
  8795. $0041  paintRRect      rect (see Note # 5 )                  8
  8796. $0042  eraseRRect      rect (see Note # 5 )                  8
  8797. $0043  invertRRec      rect (see Note # 5 )                  8
  8798. $0044  fillRRect       rect (see Note # 5 )                  8
  8799. $0045  reserved        opcode + 8 bytes data                 8
  8800. $0046  reserved        opcode + 8 bytes data                 8
  8801. $0047  reserved        opcode + 8 bytes data                 8
  8802. $0048  frameSameRRect  rect                                  0
  8803. $0049  paintSameRRect  rect                                  0
  8804. $004A  eraseSameRRect  rect                                  0
  8805. $004B  invertSameRRect rect                                  0
  8806. $004C  fillSameRRect   rect                                  0
  8807. $004D  reserved        opcode                                0
  8808. $004E  reserved        opcode                                0
  8809. $004F  reserved        opcode                                0
  8810. $0050  frameOval       rect                                  8
  8811. $0051  paintOval       rect                                  8
  8812. $0052  eraseOval       rect                                  8
  8813. $0053  invertOval      rect                                  8
  8814. $0054  fillOval        rect                                  8
  8815. $0055  reserved        opcode + 8 bytes data                 8
  8816. $0056  reserved        opcode + 8 bytes data                 8
  8817. $0057  reserved        opcode + 8 bytes data                 8
  8818. $0058  frameSameOval   rect                                  0
  8819. $0059  paintSameOval   rect                                  0
  8820. $005A  eraseSameOval   rect                                  0
  8821. $005B  invertSameOval  rect                                  0
  8822. $005C  fillSameOval    rect                                  0
  8823. $005D  reserved        opcode                                0
  8824. $005E  reserved        opcode                                0
  8825. $005F  reserved        opcode                                0
  8826. $0060  frameArc        rect, startAngle, arcAngle            12
  8827. $0061  paintArc        rect, startAngle, arcAngle            12
  8828. $0062  eraseArc        rect, startAngle, arcAngle            12
  8829. $0063  invertArc       rect, startAngle, arcAngle            12
  8830. $0064  fillArc         rect, startAngle, arcAngle            12
  8831. $0065  reserved        opcode + 12 bytes                     12
  8832. $0066  reserved        opcode + 12 bytes                     12
  8833. $0067  reserved        opcode + 12 bytes                     12
  8834. $0068  frameSameArc    rect                                  4
  8835. $0069  paintSameArc    rect                                  4
  8836. $006A  eraseSameArc    rect                                  4
  8837. $006B  invertSameAr    rect                                  4
  8838. $006C  fillSameArc     rect                                  4
  8839. $006D  reserved        opcode + 4 bytes                      4
  8840. $006E  reserved        opcode + 4 bytes                      4
  8841. $006F  reserved        opcode + 4 bytes                      4
  8842. $0070  framePoly       poly                                  polygon size
  8843. $0071  paintPoly       poly                                  polygon size
  8844. $0072  erasePoly       poly                                  polygon size
  8845. $0073  invertPoly      poly                                  polygon size
  8846. $0074  fillPoly        poly                                  polygon size
  8847. $0075  reserved        opcode + poly
  8848. $0076  reserved        opcode + poly
  8849. $0077  reserved        opcode word + poly
  8850. $0078  frameSamePoly   (not yet implemented:                 0 
  8851.                         same as 70, etc)
  8852. $0079  paintSamePoly   (not yet implemented)                 0
  8853. $007A  eraseSamePoly   (not yet implemented)                 0
  8854. $007B  invertSamePoly  (not yet implemented)                 0
  8855. $007C  fillSamePoly    (not yet implemented)                 0
  8856. $007D  reserved        opcode                                0
  8857. $007E  reserved        opcode                                0
  8858. $007F  reserved        opcode                                0
  8859. $0080  frameRgn        rgn                                   region size
  8860. $0081  paintRgn        rgn                                   region size
  8861. $0082  eraseRgn        rgn                                   region size
  8862. $0083  invertRgn       rgn                                   region size
  8863. $0084  fillRgn         rgn                                   region size
  8864. $0085  reserved        opcode + rgn                          region size
  8865. $0086  reserved        opcode + rgn                          region size
  8866. $0087  reserved        opcode + rgn                          region size
  8867. $0088  frameSameRgn    (not yet implemented- 0 same as 80, etc.)
  8868. $0089  paintSameRgn    (not yet implemented)                 0
  8869. $008A  eraseSameRgn    (not yet implemented)                 0
  8870. $008B  invertSameRgn   (not yet implemented)                 0
  8871. $008C  fillSameRgn     (not yet implemented)                 0
  8872. $008D  reserved        opcode                                0
  8873. $008E  reserved        opcode                                0
  8874. $008F  reserved        opcode                                0
  8875. $0090  BitsRect        copybits, rect clipped                variable: 
  8876.                                                              see Table 4
  8877. $0091  BitsRgn         copybits, rgn clipped                 variable: 
  8878.                                                              see Table 4
  8879. $0092  reserved        opcode + 2 bytes data                 2+ data
  8880.                        length + data                         length
  8881. $0093  reserved        opcode + 2 bytes data                 2+ data
  8882.                        length + data                         length
  8883. $0094  reserved        opcode + 2 bytes data                 2+ data
  8884.                        length + data                         length
  8885. $0095  reserved        opcode + 2 bytes data                 2+ data
  8886.                        length + data                         length
  8887. $0096  reserved        opcode + 2 bytes data                 2+ data
  8888.                        length + data                         length
  8889. $0097  reserved        opcode + 2 bytes data                 2+ data
  8890.                        length + data                         length
  8891. $0098  PackBitsRect    packed copybits, rect                 variable:         
  8892.                        clipped                               see Table 4
  8893. $0099  PackBitsRgn     packed copybits, rect                 variable:         
  8894.                        clipped                               see Table 4
  8895. $009A  *DirectBitsRect PixMap, srcRect, dstRect, mode        variable
  8896.                        (Word), PixData                       see Table 4
  8897. $009B  *DirectBitsRgn  PixMap, srcRect, dstRect, mode        variable
  8898.                        (Word), maskRgn, PixData              see Table 4
  8899. $009C  reserved        opcode + 2 bytes data                 2+ data
  8900.                        length + data                         length
  8901. $009D  reserved        opcode + 2 bytes data                 2+ data
  8902.                        length + data                         length
  8903. $009E  reserved        opcode + 2 bytes data                 2+ data
  8904.                        length + data                         length
  8905. $009F  reserved        opcode + 2 bytes data                 2+ data
  8906.                        length + data                         length
  8907. $00A0  ShortComment    kind (word)                           2
  8908. $00A1  LongComment     kind (word), size                     4+data
  8909.                        (word), data
  8910. $00A2  reserved        opcode + 2 bytes data                 2+ data
  8911.                        length + data                         length
  8912. :      :               :                                     
  8913. :      :               :
  8914. $00AF  reserved        opcode + 2 bytes data                 2+ data 
  8915.                        length + data                         length
  8916. $00B0  reserved        opcode                                0
  8917. :      :               :                                     
  8918. :      :               :
  8919. $00CF  reserved        opcode                                0
  8920. $00D0  reserved        opcode + 4 bytes data                 4+ data
  8921.                        length + data                         length
  8922. :      :               :
  8923.  
  8924. :      :               :
  8925.  
  8926. $00FE  reserved        opcode + 4 bytes data                 4+ data
  8927.                        length + data                         length
  8928. $00FF  opEndPic        end of picture                        2
  8929. $0100  reserved        opcode + 2 bytes data                 2
  8930. :      :               :
  8931. :      :               :
  8932.  
  8933. $01FF  reserved        opcode + 2 bytes data                 2
  8934. $0200  reserved        opcode + 4 bytes data                 4
  8935. :      :               :
  8936.  
  8937. $0BFF  reserved        opcode + 4 bytes data                 22
  8938. $0C00  *HeaderOp       Version (word), reserved              24
  8939.                        (word), Hres, VRes (Fixed),  
  8940.                        SrcRect (Rect), reserved (Long)
  8941. $0C01  reserved        opcode + 4 bytes data                 24
  8942. :      :               :
  8943.  
  8944. $7F00  reserved        opcode + 254 bytes data               254
  8945. :      :               :
  8946.  
  8947. $7FFF  reserved        opcode + 254 bytes data               254
  8948. $8000  reserved        opcode                                0
  8949. :      :               :
  8950.  
  8951. $80FF  reserved        opcode                                0
  8952. $8100  reserved        opcode + 4 bytes data                 4+ data
  8953.                        length + data                         length
  8954. :      :               :
  8955.  
  8956. $FFFF  reserved        opcode + 4 bytes data                 4+ data
  8957.                        length + data                         length
  8958. ________________________________________________________________________
  8959.  
  8960. Notes to Table 3
  8961.  
  8962. 1. Remember, opcode size is 1 byte for PICT, 2 bytes for PICT2.
  8963.  
  8964. 2. Because opcodes must be word aligned in version 2 pictures, a byte of 0 
  8965. (zero) data is added after odd-size data.
  8966.  
  8967. 3. The size of reserved opcodes has been defined. They can occur only in version
  8968. 2 pictures.
  8969.  
  8970. 4. All unused opcodes are reserved for future Apple use and should not be used.
  8971.  
  8972. 5. For opcodes $0040–$0044: rounded-corner rectangles use the setting of the
  8973. ovSize point (refer to opcode $000B)
  8974. 6. For opcodes $0090 and $0091: data is unpacked. These opcodes can only be used
  8975. for rowbytes less than 8.
  8976.  
  8977. 7. For opcodes $0100–$7FFF: the amount of data for opcode $nnXX = 2 * nn bytes.
  8978.  
  8979.  
  8980.  
  8981. The New Opcodes: Expanded Format
  8982.  
  8983. The expanded format of the version 2 PICT opcodes is shown in Table 4 below. 
  8984.  
  8985. Table 4. Data Format of Version 2 PICT Opcodes 
  8986. ________________________________________________________________________
  8987. Opcode Name            Description                    Reference           
  8988.                                                       to Notes
  8989.  
  8990. $002C  fontName        ID and name of font             See Note 1
  8991. $009A  DirectBitsRect  PixMap, src and dst             See Note 2
  8992.                        rects, mode, and PixData
  8993. $009B  DirectBitsRgn   PixMap, src and dst             See Note 2
  8994.                        rects, mode, maskRgn,
  8995.                        PixData
  8996. $0C00  HeaderOp        Version (Word), reserved Word,  See Note 3
  8997.                        Hres, VRes (Fixed), SrcRect 
  8998.                        (Rect), reserved (Word)
  8999.  
  9000. ________________________________________________________________________
  9001.  
  9002. Notes to Table 4
  9003.  
  9004. 1. The fontName information begins with a word containing the field’s data
  9005. length, followed by a word containing the old font ID, a byte containing the
  9006. length of the font name, and the font name itself.
  9007.  
  9008.  
  9009. 2. Unlike previous Bits opcodes, the DirectBits opcodes store the baseAddr field
  9010. of the pixMap structure in a PICT2. For compatibility with existing systems the
  9011. baseAddr field is set to $000000FF. On systems without direct pixel support,
  9012. opcodes $009A and $009B read a word from the picture and then skip that much
  9013. data. The next opcode fetched from the picture is $00FF, which terminates
  9014. picture playback.
  9015.  
  9016.  
  9017. The DirectBitsRect opcode will be followed by this structure:
  9018.  
  9019.  
  9020.   pixMap:           { described below } 
  9021.   srcRect:   Rect;  { source rectangle } 
  9022.   dstRect:   Rect;  { destination rectangle } 
  9023.   mode:      word;  { transfer mode }  
  9024.   pixData:          { described below }
  9025.  
  9026. The DirectBitsRgn opcode will be followed by this structure:
  9027.  
  9028.  
  9029.   pixMap:           { described below }  
  9030.   srcRect:  Rect;   { source rectangle }  
  9031.   dstRect:  Rect;   { destination rectangle }  
  9032.   mode:     word;   { transfer mode }   
  9033.   maskRgn:  Region; { region for masking }  
  9034.   pixData:          { described below }
  9035.  
  9036. The following pseudocode describes the pixData data type.
  9037.  
  9038.  
  9039. pixData:  
  9040.  
  9041.   If packType = 1 (unpacked) or rowbytes < 8 then data is unpacked, and
  9042.     data size = rowBytes * (bounds.bottom-bounds.top);
  9043.  
  9044.   If packType = 2 (drop pad byte) then the high-order pad byte of a     
  9045.     32-bit direct pixel is dropped, and
  9046.     data size = (3/4) * rowBytes * (bounds.bottom-bounds.top);
  9047.  
  9048.   If packType > 2 (packed) then 
  9049.     Image contains (bounds.bottom-bounds.top) packed scanlines
  9050.     Each scanline consists of [byteCount] [data].
  9051.     If rowBytes > 250 then byteCount is a word, else it is a byte.
  9052.  
  9053. In a picture, the packType field of a pixMap specifies the manner in which the
  9054. pixData was compressed.  To facilitate banding of images when memory is short,
  9055. all data compression is done on a scanline basis. The currently defined packing
  9056. schemes are:
  9057.   
  9058. 1 = no packing
  9059.  
  9060. 2 = remove pad byte—supported only for 32-bit pixels (24-bit data)
  9061.  
  9062. 3 = run length encoding by pixelSize chunks, one scanline at a time—supported
  9063. only for 16-bit pixels
  9064.  
  9065. 4 = run length encoding all of one component at a time, one scanline at a time,
  9066. red component first—supported only for 32-bit pixels (24-bit data)
  9067.  
  9068. For future compatibility, other packType values skip scanline data and draw
  9069. nothing. Since pixMap data in memory is assumed to be unpacked regardless of the
  9070. packType field value, packType can be used to tell the picture-recording
  9071. mechanism what packing technique to use on that data. A packType value of zero
  9072. in memory indicates that the default packing scheme should be used. As a general
  9073. rule, using the default packing scheme is recommended. Currently, the default
  9074. packType for pixelSize=16 is scheme 3, for pixelSize=32 it is scheme 4.
  9075. Regardless of the setting of packType at the time of picture recording, the
  9076. packType actually used to save the image will be recorded in the picture.
  9077.  
  9078. Since each scanline of packed data is preceded by a byte count, packSize is not
  9079. used and must be zero for future compatibility.
  9080.  
  9081. When the pixel type is direct chunky, cmpCount * cmpSize ≤ pixelSize.  For
  9082. storing 24 bit data in a 32 bit pixel, cmpSize would be eight and cmpCount would
  9083. be three.  If you set cmpCount = 4 then the high byte will be compressed by
  9084. packing scheme 4 and stored in the picture.
  9085.  
  9086. 3. The headerOp information is passed to the OpenCPicture routine as a
  9087. PictureHeader record, which has the structure:
  9088.  
  9089. TYPE
  9090.   PictureHeader = Record
  9091.     version:   word;
  9092.     reserved:  word;
  9093.     HRes:      Fixed;
  9094.     VRes:      Fixed;
  9095.     SrcRect:   Rect
  9096.     END;
  9097.  
  9098.  
  9099. _______________________________________________________________________________
  9100.  
  9101. æKY Summary…of…Color…Quickdraw…Changes
  9102. æC »SUMMARY OF COLOR QUICKDRAW CHANGES                                     Color QuickDraw
  9103. _______________________________________________________________________________
  9104.  
  9105. The following cards summarize the constants, data types, and routines for Color
  9106. Quickdraw.
  9107. _______________________________________________________________________________
  9108.  
  9109. æKY Color…Quickdraw…Constants
  9110. æC »Constants                                                              Color QuickDraw
  9111. _______________________________________________________________________________
  9112.  
  9113. CONST
  9114.  
  9115. {New Constants for Color QuickDraw}
  9116.  
  9117. ditherCopy  = 64;  {Dither mode for Copybits}
  9118. RGBDirect   = 16;  {16 & 32 bits/pixel pixelType value}
  9119. _______________________________________________________________________________
  9120.  
  9121. æKY Color…Quickdraw…Data…Types
  9122. æC »Data Types                                                             Color QuickDraw
  9123. _______________________________________________________________________________
  9124.  
  9125. PICT2Header = 
  9126. RECORD
  9127.   version:   word;   {set to -2}
  9128.   reserved:  word;   {reserved for future use}
  9129.   hRes:      Fixed;  {best horizontal resolution}
  9130.   vRes:      Fixed;  {best vertical resolution}
  9131.   SrcRect:   Rect    {source rectangle for best display}
  9132.                      {at hRes, vRes resolution}
  9133.   END;
  9134. _______________________________________________________________________________
  9135.  
  9136. æKY Color…Quickdraw…Routines
  9137. æC »Routines                                                               Color QuickDraw
  9138. _______________________________________________________________________________
  9139.  
  9140. FUNCTION OpenCPicture  (newHeader: PICT2Header) : PicHandle;
  9141. FUNCTION GetCTable  (ctID: Integer) : CTabHandle;
  9142. FUNCTION BitMapToRegion  (region:RGNHandle; bMap:BitMap) : OSErr;
  9143. PROCEDURE CTabChanged  (ctab: CTabHandle);
  9144. PROCEDURE PixPatChanged  (ppat: PixPatHandle);
  9145. PROCEDURE GDeviceChanged  (gdh: GDHandle);
  9146. FUNCTION QDDone (port:GrafPtr) : Boolean;
  9147. _______________________________________________________________________________
  9148.  
  9149. æKY Color…Quickdraw…Result…Codes
  9150. æC »Result Codes                                                           Color QuickDraw
  9151. _______________________________________________________________________________
  9152.  
  9153. QDErr              -147  Region too big
  9154. pixmapTooDeepErr   -148  PixMap record is deeper than 1 bit per pixel
  9155. QDErr              -149  Insufficient stack
  9156. rgnTooBigErr       -500  BitMap would convert into a region greater than 32 KB 
  9157. _______________________________________________________________________________
  9158.  
  9159.  
  9160. æKY CompatibilityGuidelines
  9161. æC 
  9162. _______________________________________________________________________________
  9163.  
  9164. COMPATIBILITY GUIDELINES
  9165. _______________________________________________________________________________
  9166.  
  9167. About…the…Compatibility…Guidelines…Chapter
  9168. About…Compatibility
  9169.     Using…Memory…Wisely
  9170.     Using…Assembly…Language
  9171.     Accessing…Hardware
  9172.     Using…Low-Memory…Global…Variables
  9173.     Determining…Whether…a…Trap…Is…Available
  9174. Running…in…System…Software…Version…7.0
  9175.     Allowing…Multiple…Applications
  9176.     Supporting…Standard…AppleEvents
  9177.     Selecting…AppleEvents…to…Support
  9178.     Isolating…User…Interface…Code
  9179.     Modifying…the…Event…Loop
  9180.     Indicating…an…Application…Is…AppleEvent-Aware
  9181.     Removing…Font…Size…Restrictions
  9182.     Operating…With…Virtual…Memory
  9183. Localizing…Macintosh…Programs
  9184.     General…Guidelines…for…Compatibility
  9185.     Other…Localization…Tools
  9186. Running…Macintosh…Programs…Under…A/UX
  9187.     How…the…A/UX…Toolbox…Works
  9188.     Using…the…A/UX…Toolbox
  9189.     A/UX…Compatibility…Guidelines
  9190. About…the…Gestalt…Manager
  9191. Using…the…Gestalt…Manager
  9192.     Determining…Features…of…the…Operating…Environment
  9193.     Determining…Whether…Gestalt…Is…Available
  9194.     Interpreting…Gestalt…Responses
  9195.     Interpreting…Responses…to…Environmental…Selectors
  9196.     Interpreting…Responses…to…Informational…Selectors
  9197.     Adding…Gestalt…Selectors
  9198.     Modifying…Gestalt…Selectors
  9199.     Specifying…Gestalt…Selector…Functions
  9200. Gestalt…Manager…Routines
  9201.     Getting…Information…About…the…Operating…Environment
  9202.     Adding…Selector…Codes
  9203.     Modifying…Selector…Codes
  9204. Summary…of…the…Gestalt…Manager
  9205.     Gestalt…Manager…Constants
  9206.     Gestalt…Manager…Routines…Summary
  9207.     Gestalt…Manager…Result…Codes
  9208. _______________________________________________________________________________
  9209.  
  9210.  
  9211.  
  9212. æKY About…the…Compatibility…Guidelines…Chapter
  9213. æC »ABOUT THIS CHAPTER                                            Compatibility Guidelines
  9214. _______________________________________________________________________________
  9215.  
  9216. This chapter describes how you can write applications that have the greatest
  9217. chance of operating on all models of the Macintosh® computer, regardless of the
  9218. hardware components found on any particular machine and of the available system
  9219. software, managers, and device drivers. It addresses how you can take advantage
  9220. of features that are new to system software version 7.0 in ways that are least
  9221. likely to cause problems for users who are not running version 7.0. In a word,
  9222. this chapter provides as much advice as possible to help you achieve maximum
  9223. compatibility for your applications on all Macintosh computers, including those
  9224. running version 7.0.
  9225.  
  9226. System software version 7.0 provides the most important test of software
  9227. compatibility since the introduction of the Macintosh II, and you must
  9228. understand how you may need to revise your current applications so that they
  9229. operate correctly with this new system software. Fortunately, if you have
  9230. followed the guidelines given in previous volumes of Inside Macintosh, your
  9231. applications stand a very good chance of working correctly in version 7.0
  9232. without any modification whatsoever. However, version 7.0 introduces many new
  9233. features and capabilities that you may wish to use in your applications, without
  9234. sacrificing compatibility with earlier versions of system software. This chapter
  9235. provides a number of additional guidelines to help you revise existing
  9236. applications to take advantage of version 7.0 features while retaining
  9237. compatibility with previous system software.
  9238.  
  9239. System software version 7.0, with its multitasking environment and its new
  9240. emphasis on communication and cooperation among applications, places certain
  9241. responsibilities on applications. As a result, you must be more aware than ever
  9242. of the programming shortcuts that can result in incompatibility.
  9243.  
  9244. This chapter focuses on several aspects of writing software that is compatible
  9245. with all Macintosh computers:
  9246.  
  9247.   •   what can cause compatibility problems and how in general to avoid those
  9248.       problems
  9249.  
  9250.   •   how to write applications that execute in both version 6.0 and version
  9251.       7.0 system software
  9252.  
  9253.   •   how to determine what software and hardware features are available on a
  9254.       particular machine
  9255.  
  9256.   •   how to write applications that execute under A/UX®, Apple’s version of
  9257.       the UNIX® operating system
  9258.  
  9259.   •   how to write software that can be easily modified for use in other
  9260.       countries
  9261.  
  9262. This chapter also describes the Gestalt Manager, a set of three new Operating
  9263. System functions that provide applications with a simple and efficient method
  9264. for determining what software and hardware features are available on a given
  9265. machine. You need to use the Gestalt Manager if your application takes advantage
  9266. of particular hardware components (such as a floating-point unit) or software
  9267. modules (such as Color QuickDraw™) that are not available on all Macintosh
  9268. computers. Your application can also use the Gestalt Manager to inform the
  9269. Operating System (and hence other applications) that it is present in the
  9270. current environment.
  9271.  
  9272. The Gestalt Manager is available in system software version 7.0. It is also
  9273. included in system software versions 6.0.4 and 6.0.5, and in ROM on two
  9274. machines, the Macintosh IIci and the Macintosh Portable. Your development system
  9275. may supply code that allows you to call Gestalt on earlier system software
  9276. versions; check the documentation provided with your development system to see
  9277. if this is possible. Of course, since you cannot use Gestalt to determine if it
  9278. is present, you must do that in some other way; one such method is illustrated
  9279. in 
  9280. “Determining Whether Gestalt Is Available” later in this chapter.
  9281.  
  9282. You need to read this chapter if you are interested in writing applications that
  9283. execute on as many Macintosh computers as possible or under alternate operating
  9284. systems such as A/UX. In particular, if you wish to enhance an existing product
  9285. so that it supports new features of system software version 7.0 but also
  9286. executes correctly in earlier versions of system software, or if you wish to
  9287. write a new product that executes only in version 7.0, you should look at 
  9288. “Running In System Software Version 7.0.” You should read the sections on the
  9289. Gestalt Manager later in this chapter if you need to take advantage of specific
  9290. software or hardware features that may not be present on all versions of the
  9291. Macintosh, or if you wish to inform other applications of the presence of your
  9292. application in the operating environment.
  9293.  
  9294. If you want your applications to run in system software versions earlier than
  9295. 6.0.4 (where the Gestalt function is not available), you should be familiar with
  9296. the Environs procedure, discussed in the Operating System Utilities chapter of
  9297. Volumes II and IV, and the SysEnvirons function, discussed in the Compatibility
  9298. Guidelines chapter of Volume V. Both Environs and SysEnvirons perform the kind
  9299. of function that Gestalt performs—they allow you to determine what features are
  9300. available on a specific machine. For reasons outlined later, however, you should
  9301. not use either of these routines if the Gestalt function is available.
  9302.  
  9303. Unfortunately, no single chapter can provide all the information you need to
  9304. achieve the greatest possible compatibility for your applications. Most of the
  9305. subsequent chapters in this volume (and indeed all previous volumes of Inside
  9306. Macintosh) contain numerous warnings and guidelines that you should heed if you
  9307. wish to increase the likelihood that your applications will execute correctly on
  9308. all members of the Macintosh family and under alternate operating systems such
  9309. as A/UX. The Memory Management chapter in this volume, for example, contains a
  9310. fuller account of 32-bit clean programming than is given here and is essential
  9311. reading for all developers. (An application is 32-bit clean if it can use all 32
  9312. bits of a handle or pointer for memory addressing.) Similarly, the guidelines
  9313. given in this chapter on writing A/UX-compatible Macintosh programs summarize
  9314. and complement, but do not replace, the discussion in the separate publication 
  9315. A/UX Toolbox: Macintosh ROM Interface. So the complete story on Macintosh
  9316. software compatibility does not end with this chapter, but it does begin here.
  9317.  
  9318. _______________________________________________________________________________
  9319.  
  9320. æKY About…Compatibility
  9321. æC »ABOUT COMPATIBILITY                                           Compatibility Guidelines
  9322. _______________________________________________________________________________
  9323.  
  9324. Compatibility is the ability of a program to execute properly in different
  9325. operating environments. Compatibility is important if you want to write software
  9326. that runs, with little or no modification, on all members of the Macintosh
  9327. family and in all system software versions. If you want to take advantage of
  9328. particular software or hardware features that may not be present on all
  9329. Macintosh computers, you need to know how to determine when those features are
  9330. available.
  9331.  
  9332. To appreciate why compatibility is a real and sometimes vexing concern, imagine
  9333. that from all the Macintosh computers currently in operation in the world, you
  9334. were to choose two at random. You would quite likely find a great number of
  9335. differences in the hardware and software configurations on those two machines.
  9336. You might find different CPUs, different memory management units (MMUs),
  9337. different amounts of RAM, different shapes and sizes of monitors, and so forth.
  9338. You are also likely to find different versions of system software, different ROM
  9339. versions, different AppleTalk® drivers, different versions of managers,
  9340. different printer interfaces, and so forth. Ideally, you want your product to
  9341. run on both of those machines, regardless of the many significant differences
  9342. between them. If you succeed in writing your application so that it does operate
  9343. on both of those machines, you have succeeded in writing compatible software.
  9344.  
  9345. This section provides a number of guidelines that you should follow if you want
  9346. your applications to run on the greatest number of Macintosh computers. Some of
  9347. these guidelines are quite general and apply to all programs; some apply only if
  9348. you are programming in assembly language.
  9349.  
  9350. One key to achieving compatibility is not to depend on things that may change.
  9351. Inside Macintosh contains numerous warnings about which information is likely to
  9352. change. As the Operating System and User Interface Toolbox evolve to accommodate
  9353. the needs of developers and users, many of the elements will vary. Whenever
  9354. possible, Apple strives to add features without altering existing interfaces. In
  9355. general, you can assume that Operating System and Toolbox routines are less
  9356. likely to change than data structures. Therefore, you should never manipulate
  9357. data structures directly, even if their structure is documented. Instead, you
  9358. should manipulate those structures only indirectly, by calling Operating System
  9359. and Toolbox routines that achieve the desired effect. In particular, you should
  9360. never alter any portion of a data structure marked as unused or reserved.
  9361.  
  9362. Another key to writing compatible code is to code defensively. Do not assume
  9363. that users perform actions in a particular order, and do not assume that
  9364. function and procedure calls always succeed. You should always test the return
  9365. values of routines for errors, as illustrated in most of the code samples
  9366. presented in this volume.
  9367.  
  9368. _______________________________________________________________________________
  9369.  
  9370. æKY Using…Memory…Wisely
  9371. æC »Using Memory Wisely                                           Compatibility Guidelines
  9372. _______________________________________________________________________________
  9373.  
  9374. A major cause of compatibility problems, especially in connection with
  9375. applications running in the A/UX operating system, is misuse of the Memory
  9376. Manager . Here are some important points to keep in mind:
  9377.  
  9378.   • Do not set bits in master pointers directly. Use Memory Manager traps (for
  9379.     example, HLock) instead.
  9380.  
  9381.   • Always check the handle or pointer returned by a routine to make certain
  9382.     that it is not NIL. A NIL handle may indicate that a memory allocation
  9383.     failed, or that a requested resource could not be found.
  9384.  
  9385.   • Always check that a handle marked as purgeable has not been purged before
  9386.     using that handle. For example:
  9387.  
  9388.       IF myHandle^ <> NIL THEN  {handle not purged}
  9389.  
  9390.   • Do not create your own handles; instead, use the Memory Manager function
  9391.     NewHandle.
  9392.  
  9393.   • Never make assumptions about the contents of Memory Manager data structures.
  9394.  
  9395. If you have followed all these guidelines, it is likely that your application is
  9396. 32-bit clean, that is, that it operates correctly in an environment where all 32
  9397. bits of handles and pointers are used to store memory addresses. In system
  9398. software version 7.0 and A/UX, your applications must be 32-bit clean or they
  9399. may not operate correctly. See the Memory Management chapter in this volume for
  9400. more information about these points.
  9401.  
  9402. _______________________________________________________________________________
  9403.  
  9404. æKY Using…Assembly…Language
  9405. æC »Using Assembly Language                                       Compatibility Guidelines
  9406. _______________________________________________________________________________
  9407.  
  9408. In general, your software should not include 68000 instructions that require the
  9409. processor to be in supervisor mode; these include instructions that modify the
  9410. contents of the Status Register (SR). Programmers typically modify the SR only
  9411. as a means of changing the Condition Code Register (CCR) half of the SR; in
  9412. these cases, an instruction that addresses the CCR directly will work instead.
  9413. Do not use the User Stack Pointer or turn interrupts on and off.
  9414.  
  9415. If you wish to handle your own exceptions (thereby relying on the position of
  9416. data in the exception’s local stack frame), be aware that exception stack frames
  9417. vary within the 68000 family.
  9418.  
  9419. In particular, don’t use the TRAP instruction. Also, the TAS instruction, which
  9420. uses a special read-modify-write memory cycle, is not supported by the Macintosh
  9421. SE and Macintosh II hardware.
  9422.  
  9423. A memory management unit available in some Macintosh computers may prevent code
  9424. from writing to addresses within code segments. Also, the 68020 and 68030 cache
  9425. code as it is encountered. You should allocate data blocks on the stack or in
  9426. heap blocks separate from the code, and your code should not modify itself.
  9427.  
  9428. _______________________________________________________________________________
  9429.  
  9430. æKY Accessing…Hardware
  9431. æC »Accessing Hardware                                            Compatibility Guidelines
  9432. _______________________________________________________________________________
  9433.  
  9434. You should never address hardware directly; whenever possible, use the routines
  9435. provided by the various device drivers and managers to send data to the
  9436. available hardware. The addresses of memory-mapped hardware (like the VIA1,
  9437. VIA2, SCC, and so forth) are always subject to change, as is the hardware
  9438. itself. More important, direct access to such hardware is not possible in every
  9439. operating environment. In multiuser systems like A/UX, for instance, the
  9440. operating system manipulates all hardware; applications simply cannot write
  9441. directly to hardware addresses.
  9442.  
  9443. You should also avoid writing directly to the screen. Use QuickDraw routines
  9444. whenever possible to draw on the screen. If you absolutely must write directly
  9445. to the screen, do not assume that the screen is a fixed size or that it is in a
  9446. fixed location. The location, size, and bit depth of the screen differ in
  9447. various machines. Instead, you should read the QuickDraw global variable
  9448. screenBits.bounds to determine the size of the screen, screenBits.baseAddr to
  9449. determine the start of the screen, and screenBits.rowBytes to determine the
  9450. offset between rows. On machines with Color QuickDraw, the device list 
  9451. (described in the Graphics Devices chapter in this volume) tells the location,
  9452. size, and bit depth of each screen, screenBits contains the location and size of
  9453. the main device, and GrayRgn contains a region describing the shape and size of
  9454. the desktop.
  9455.  
  9456. _______________________________________________________________________________
  9457.  
  9458. æKY Using…Low-Memory…Global…Variables
  9459. æC »Using Low-Memory Global Variables                             Compatibility Guidelines
  9460. _______________________________________________________________________________
  9461.  
  9462. Don’t rely on low-memory global variables. Many of these variables have been
  9463. previously documented in Inside Macintosh, but many have not. In particular, you
  9464. must avoid undocumented low-memory global variables, because they are most
  9465. likely to change. But you should even avoid well-known global variables, since
  9466. they may not be available in all environments or in the future. In general, you
  9467. can avoid using low-memory global variables by using available routines that
  9468. return the same information. For example, the TickCount function returns the
  9469. same value that is contained in the low-memory global variable Ticks. TickCount
  9470. is available under A/UX, but Ticks is not. So you can increase the likelihood of
  9471. compatibility with A/UX by using the routine and not the global variable.
  9472.  
  9473. _______________________________________________________________________________
  9474.  
  9475. æKY Determining…Whether…a…Trap…Is…Available
  9476. æC »Determining Whether a Trap Is Available                       Compatibility Guidelines
  9477. _______________________________________________________________________________
  9478.  
  9479. One important way that the Operating System and Toolbox have changed through
  9480. successive versions of the ROM and system software is by the addition of
  9481. numerous new traps. For example, the Time Manager released with system software
  9482. version 7.0 includes a new trap, InsXTime, that provides certain improvements
  9483. over the existing trap, InsTime. By using InsXTime instead of InsTime, your
  9484. application can ensure that the periodic actions it requests will execute at a
  9485. fixed frequency that does not drift over time. Before using a trap that is not
  9486. available on all machines, however, you need to determine whether it is
  9487. available; if you call InsXTime on a machine that does not implement it, your
  9488. program will crash.
  9489.  
  9490. Your application can check the availability of a particular trap such as
  9491. InsXTime in one of two ways. First, you can call the Gestalt function that is
  9492. discussed later in this chapter to see if the appropriate version of the
  9493. corresponding driver or manager is available. For example, the trap InsXTime is
  9494. included in the extended Time Manager but not in earlier versions of the Time
  9495. Manager. So you could use Gestalt to determine which version of the Time Manager
  9496. is available in the current operating environment. If Gestalt reports that the
  9497. extended Time Manager is present, you can safely call InsXTime to queue your
  9498. request.
  9499.  
  9500. There are several cases, however, in which you cannot use Gestalt to determine
  9501. whether a specific trap is implemented. You cannot, for instance, use Gestalt to
  9502. determine whether the Gestalt trap itself is available. In addition, the trap
  9503. whose existence you wish to test might not be included in any manager or, if it
  9504. is, there might not be a Gestalt selector code for that manager. The
  9505. WaitNextEvent trap is a good example of this: there is no way, using Gestalt, to
  9506. determine whether WaitNextEvent is available.
  9507.  
  9508. The second way to determine the availability of a particular Operating System or
  9509. Toolbox trap is by testing directly for the existence of the trap, using the
  9510. technique illustrated in Listing 3-1. You should use this method to test whether
  9511. Gestalt is available before calling Gestalt. You should also use it to test for
  9512. the existence of traps not included in managers or drivers about which Gestalt
  9513. can report. This listing illustrates how to test the availability of
  9514. WaitNextEvent.
  9515.  
  9516. Listing 3-1.  Determining whether a trap is available
  9517.  
  9518. USES
  9519.   Types, Traps, OSUtils;
  9520.  
  9521. FUNCTION NumToolboxTraps: Integer;
  9522. BEGIN
  9523.   IF NGetTrapAddress(_InitGraf,ToolTrap) = 
  9524.         NGetTrapAddress($AA6E,ToolTrap) THEN
  9525.     NumToolboxTraps := $200
  9526.   ELSE
  9527.     NumToolboxTraps := $400;
  9528. END;
  9529.  
  9530. FUNCTION GetTrapType(theTrap: Integer): TrapType;
  9531. CONST
  9532.   TrapMask = $0800;
  9533. BEGIN
  9534.   IF BAND(theTrap,TrapMask) > 0 THEN
  9535.     GetTrapType := ToolTrap
  9536.   ELSE
  9537.     GetTrapType := OSTrap;
  9538. END;
  9539.  
  9540. FUNCTION TrapAvailable(theTrap: Integer): Boolean;
  9541. VAR
  9542.   tType: TrapType;
  9543. BEGIN
  9544.   tType := GetTrapType(theTrap);
  9545.   IF tType = ToolTrap THEN BEGIN
  9546.     theTrap := BAND(theTrap, $07FF);
  9547.     IF theTrap >= NumToolboxTraps THEN
  9548.       theTrap := _Unimplemented;
  9549.   END;
  9550.   TrapAvailable := NGetTrapAddress(theTrap, tType) <>
  9551.         NGetTrapAddress(_Unimplemented, ToolTrap);
  9552. END;
  9553.  
  9554. FUNCTION WNEAvailable: Boolean;
  9555. CONST
  9556.   _WaitNextEvent   =  $A860;  {trap number of WaitNextEvent}
  9557. BEGIN
  9558.   WNEAvailable :=  TrapAvailable(_WaitNextEvent);
  9559. END;
  9560.  
  9561. The NumToolboxTraps function relies on the fact that the InitGraf trap (trap
  9562. number $A86E) is always implemented. If the trap dispatch table is large enough 
  9563. (that is, has more than $200 entries), then $AA6E always points to either
  9564. Unimplemented or something else, but never to InitGraf. As a result, you can
  9565. check the size of the trap dispatch table by checking to see if the address of
  9566. trap $A86E is the same as $AA6E.
  9567.  
  9568. The TrapAvailable function uses the information about the size of the dispatch
  9569. table as follows: TrapAvailable first checks to see if the trap to be tested has
  9570. a trap number greater than the total number of traps available on the machine.
  9571. If so, then it sets theTrap to Unimplemented before testing it against the
  9572. Unimplemented trap.
  9573.  
  9574. Note:  The technique presented in Listing 3-1 for determining whether a
  9575. particular trap is available differs from techniques previously supported by
  9576. Apple. The previous method determined the size of the trap dispatch table by
  9577. checking the machine type. This type of check should not be used for any
  9578. purposes other than simply displaying the information, as explained in “Using
  9579. the Gestalt Manager.”  
  9580. _______________________________________________________________________________
  9581.  
  9582. æKY Running…in…System…Software…Version…7.0
  9583. æC »RUNNING IN SYSTEM SOFTWARE VERSION 7.0                        Compatibility Guidelines
  9584. _______________________________________________________________________________
  9585.  
  9586. You should keep in mind the guidelines given in the previous sections whenever
  9587. you are writing or revising any Macintosh application. If you heed those
  9588. guidelines, you are likely to produce applications that run reasonably well in
  9589. all environments, including system software version 7.0. So those guidelines
  9590. define a minimal level of conformance necessary for your applications to run in
  9591. version 7.0. Applications that conform to the programming interfaces documented
  9592. in Inside Macintosh and that violate none of the guidelines presented earlier in
  9593. this chapter are called 7.0-compatible because they run in version 7.0 without
  9594. problems.
  9595.  
  9596. An application can be 7.0-compatible, however, without taking advantage of the
  9597. many new features available in system software version 7.0 and without
  9598. exhibiting an awareness that other applications may be present and may wish to
  9599. use processor time that would otherwise go unused. Among those that do take
  9600. advantage of such features, there are at least two levels of involvement with
  9601. version 7.0. An application is 7.0-friendly if it takes advantage of some of the
  9602. special features of version 7.0 when executing under that environment, but is
  9603. still able to perform all its principal functions when executing in version 6.0.
  9604. An application is 7.0-dependent if it requires the existence of features that
  9605. are available only in version 7.0; it might not even run in version 6.0. Even if
  9606. 7.0-dependent applications do execute in version 6.0, they are virtually
  9607. guaranteed to offer far fewer features there than in version 7.0. A good example
  9608. of a 7.0-dependent application is a multimedia application that needs to do
  9609. real-time mixing of multiple channels of stereo sound. The Sound Manager
  9610. included with system software version 7.0 provides support for stereo output and
  9611. the ability to mix multiple independent channels of sampled sound; neither of
  9612. these features is available, however, with the Sound Manager provided with
  9613. version 6.0 or earlier.
  9614.  
  9615. The situation is similar to deciding whether your applications should use Color
  9616. QuickDraw. If you revise existing black-and-white drawing programs to
  9617. incorporate color, your applications operate either with or without Color
  9618. QuickDraw. If you introduce new applications that require Color QuickDraw, they
  9619. simply do not run on machines that don’t support color.
  9620.  
  9621. The rest of this section gives guidelines on what you can do to existing
  9622. applications to make them 7.0-friendly and not simply 7.0-compatible. The
  9623. following pages describe in overview how to
  9624.  
  9625.   •   be aware that the user may have launched multiple applications
  9626.  
  9627.   •   support the minimal set of required AppleEvents™
  9628.  
  9629.   •   remove font size restrictions to support outline fonts
  9630.  
  9631.   •   make sure that your application operates correctly with virtual memory
  9632.  
  9633. For complete details on any of these items, see the corresponding chapter in
  9634. this volume. For example, to learn what you need to do to support outline fonts
  9635. in your application, see the Font Manager chapter. (The information about
  9636. cooperating with other open applications is found in the Event Manager chapter.)
  9637.  
  9638. _______________________________________________________________________________
  9639.  
  9640. æKY Allowing…Multiple…Applications
  9641. æC »Allowing Multiple Applications                                Compatibility Guidelines
  9642. _______________________________________________________________________________
  9643.  
  9644. System software version 7.0 continues the development of the Macintosh Operating
  9645. System into a multitasking environment in which multiple applications can be
  9646. active and must share the available system resources. The facilities provided
  9647. with earlier versions of system software by the optional MultiFinder™ package
  9648. are now an integral part of system software version 7.0. This means that your
  9649. application must display a certain awareness that other applications might be
  9650. open at the same time and competing with it for processing time, memory, control
  9651. of communications ports, and so forth.
  9652.  
  9653. Although most operating systems regulate the sharing of available resources by
  9654. having the system parcel them out, the Macintosh Operating System relies on the
  9655. willingness of foreground and background applications to share those resources
  9656. among themselves. For example, each application must determine its own memory
  9657. requirements by specifying a minimum memory partition size (below which that
  9658. application does not execute) and a preferred partition size (at which the
  9659. application executes best). The Operating System itself has very little control
  9660. over the partition size allotted to the application, other than by limiting that
  9661. size to the available memory. Similarly, the Operating System has very little
  9662. control over which applications receive processing time, since the user
  9663. ultimately decides when to bring a background application into the foreground.
  9664. If your application holds onto the microprocessor for too long while being
  9665. switched into the background, other applications may appear sluggish and
  9666. unresponsive.
  9667.  
  9668. The lesson to be learned from all this is that, in system software version 7.0,
  9669. your application must be a good neighbor. You cannot expect the Operating System
  9670. to force responsible behavior on your application; rather, you must ensure that
  9671. your application can happily coexist with other open applications by following
  9672. these guidelines:
  9673.  
  9674.   •   include a 'SIZE' resource that specifies reasonable minimum and preferred
  9675.       memory partition sizes; if you occasionally need larger amounts of
  9676.       memory, use the temporary memory routines described in the Memory
  9677.       Management chapter
  9678.  
  9679.   •   use WaitNextEvent instead of GetNextEvent in your main event loop to
  9680.       obtain events from the Toolbox Event Manager; this allows other
  9681.       applications to use processor time your application doesn’t need, and
  9682.       allows your application to perform operations while it is in the
  9683.       background
  9684.  
  9685.   •   modify your main event loop to process suspend and resume events; this
  9686.       reduces the time it takes to switch your application into the foreground
  9687.       or background
  9688.  
  9689. For a more complete discussion of using WaitNextEvent and processing suspend and
  9690. resume events, see the Event Manager chapter in this volume. That chapter also
  9691. includes a description of the multitasking environment that is standard in
  9692. system software version 7.0.
  9693.  
  9694. _______________________________________________________________________________
  9695.  
  9696. æKY Supporting…Standard…AppleEvents
  9697. æC »Supporting Standard AppleEvents                               Compatibility Guidelines
  9698. _______________________________________________________________________________
  9699.  
  9700. Possibly the most significant new feature in system software version 7.0 is
  9701. interapplication communication (IAC), which will play an increasingly important
  9702. role in future versions of the Macintosh Operating System. One central part of
  9703. IAC is the addition of high-level events to those events that the Event Manager
  9704. receives and conveys to applications. High-level events allow applications to
  9705. communicate with one another by putting events in the event queue of the
  9706. receiving application.
  9707.  
  9708. Apple has defined a standard set of such high-level events, known as
  9709. AppleEvents, that are common to all or nearly all applications. Some AppleEvents
  9710. must be supported by an application that supports any AppleEvents; these are
  9711. known as required AppleEvents. With a minimal amount of work, you can modify
  9712. your main event loop so it supports the required AppleEvents. In doing so, you
  9713. increase the level of compatibility of your application and ease the transition
  9714. to the days when applications expect other applications to support AppleEvents.
  9715.  
  9716. There are four main steps you need to follow to incorporate support for the
  9717. required AppleEvents into your application: 
  9718.  
  9719. 1.  Identify the AppleEvents that you want your application to support.
  9720.  
  9721. 2.  Separate code that interacts with users from code that performs operations,
  9722.     whether requested by the user or by the required AppleEvents.
  9723.  
  9724. 3.  Modify the event loop to recognize the new type of event.
  9725.  
  9726. 4.  Inform the Operating System that your application can receive and act on the
  9727.     required AppleEvents.
  9728.  
  9729. The following four sections provide further details on each of these steps. For
  9730. a more complete story, see the Event Manager chapter in this volume.
  9731.  
  9732. _______________________________________________________________________________
  9733.  
  9734. æKY Selecting…AppleEvents…to…Support
  9735. æC »Selecting AppleEvents to Support                              Compatibility Guidelines
  9736. _______________________________________________________________________________
  9737.  
  9738. First you need to identify the AppleEvents that you want your application to
  9739. support. To make your application 7.0-friendly, you need to support the required
  9740. AppleEvents that Apple Computer, Inc. has already defined. Table 3-1 lists the
  9741. required AppleEvents, together with the parameters passed to the application
  9742. with each kind of AppleEvent.
  9743.  
  9744. Table 3-1.  Required AppleEvents
  9745.  
  9746. Event               Parameters           Description
  9747. Open Application    none                 open an application
  9748. Open Documents      list of documents    open each specified document
  9749. Print               list of documents    print each specified document
  9750. Quit                none                 terminate and exit the application
  9751. Setup               none                 update application’s menu items
  9752. Get                 property             return value of specified property
  9753.  
  9754. Your application should already contain code to accomplish these standard
  9755. operations. If so, you may still need to modify that code as described in the
  9756. next section.
  9757. _______________________________________________________________________________
  9758.  
  9759. æKY Isolating…User…Interface…Code
  9760. æC »Isolating User Interface Code                                 Compatibility Guidelines
  9761. _______________________________________________________________________________
  9762.  
  9763. You need to separate code that interacts with users from code that actually
  9764. performs the operations requested by the required AppleEvents. Generally, it is
  9765. easy to mix user interface code with code that performs some operation, so you
  9766. need to think carefully about this step. For example, many print loops have a
  9767. section that begins like this:
  9768.  
  9769. IF ( PrStlDialog(thePrRecHdl) ) THEN BEGIN
  9770.   IF ( PrJobDialog(thePrRecHdl) ) THEN BEGIN
  9771.     thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  9772.     IF ( PrError = noErr ) THEN BEGIN
  9773.       PrOpenPage(thePrPort, NIL);
  9774.  
  9775. Similarly, this fragment might execute when a user chooses Open from the File
  9776. menu:
  9777.  
  9778. IF SFGetFile(pt, str, fileFilter, numTypes,
  9779.      typeList, dlgHook, reply) THEN BEGIN
  9780.   err := FSOpen(reply.fName, reply.vRefNum, refNum);
  9781.  
  9782. Since an AppleEvent (and not the user) might instruct your application to open
  9783. or print a document, the application needs to be able to perform the requested
  9784. operation without displaying the print or file dialog boxes. A way to do this in
  9785. version 7.0 might go like this:
  9786.  
  9787. FUNCTION PresentPrintDialogs: Boolean;
  9788. VAR
  9789.   thePrRecHandle: THPrint;
  9790. BEGIN
  9791.   PresentPrintDialogs := FALSE;
  9792.   IF ( PrStlDialog(thePrRecHdl) ) THEN
  9793.     IF ( PrJobDialog(thePrRecHdl) ) THEN
  9794.       PresentPrintDialogs := TRUE;
  9795. END;
  9796.  
  9797. PROCEDURE PrintDocument(thePrRecHdl: THPrint);
  9798. VAR
  9799.   thePrPort:  TPPrPort;
  9800. BEGIN
  9801.   thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  9802.   IF ( PrError = noErr ) THEN BEGIN
  9803.     PrOpenPage(thePrPort,NIL);
  9804.   ...
  9805.   END;
  9806. END;
  9807.  
  9808. In this way, your application can respond to print requests both from the user
  9809. and from any AppleEvents it receives.
  9810.  
  9811. _______________________________________________________________________________
  9812.  
  9813. æKY Modifying…the…Event…Loop
  9814. æC »Modifying the Event Loop                                      Compatibility Guidelines
  9815. _______________________________________________________________________________
  9816.  
  9817. In system software version 7.0, the Event Manager manages three classes of
  9818. events: low-level events (which are the traditional user-initiated events like
  9819. mouse and keyboard events), operating system event (which inform applications of
  9820. changes in their operating status), and high-level event (which include
  9821. AppleEvents). AppleEvents are reported to an application using a new event type
  9822. defined by the constant kHighLevelEvent.
  9823.  
  9824. CONST  kHighLevelEvent  = 23;
  9825.  
  9826. This means that you need to add a new selector to your branch statements.
  9827. Listing 3-2 shows a simple event loop modified to accept AppleEvents.
  9828.  
  9829. Listing 3-2.  An event loop modified to receive high-level events
  9830.  
  9831. PROCEDURE DoEvent(event: EventRecord);
  9832. BEGIN
  9833.   CASE event.what OF
  9834.     nullEvent:
  9835.       DoIdle;
  9836.     mouseDown:
  9837.       DoMouseDown(event);
  9838.     mouseUp:
  9839.       DoMouseUp(event);
  9840.     keyDown, autoKey: 
  9841.       DoKeyDown(event);
  9842.     activateEvt:
  9843.       DoActivate(event);
  9844.     updateEvt:
  9845.       DoUpdate(event);
  9846.     kOSEvent:
  9847.       DoOSEvent(event);
  9848.     kHighLevelEvent:
  9849.       DoHighLevelEvent(event);
  9850.   END;
  9851. END; {DoEvent}
  9852.  
  9853. At this point, you need to provide the DoHighLevelEvent routine to handle the
  9854. AppleEvent (or other high-level event). Once you’ve separated the relevant
  9855. user-interface part of your code, modified your event loop, and added a
  9856. procedure that accepts high-level events, all you need to do is write a bit of
  9857. code that knows how to look at AppleEvents and then calls the correct operation.
  9858.  
  9859. _______________________________________________________________________________
  9860.  
  9861. æKY Indicating…an…Application…Is…AppleEvent-Aware
  9862. æC »Indicating an Application Is AppleEvent-Aware                 Compatibility Guidelines
  9863. _______________________________________________________________________________
  9864.  
  9865. The final thing you need to do is inform the Operating System that your
  9866. application is able to receive and process AppleEvents. To accomplish this, you
  9867. need to modify your application’s 'SIZE' resource, as explained in the Event
  9868. Manager chapter.
  9869.  
  9870. _______________________________________________________________________________
  9871.  
  9872. æKY Removing…Font…Size…Restrictions
  9873. æC »Removing Font Size Restrictions                               Compatibility Guidelines
  9874. _______________________________________________________________________________
  9875.  
  9876. System software version 7.0 introduces outline fonts, known as TrueType™. An
  9877. outline font can be printed or displayed at any point size without the jagged
  9878. appearance of some bitmapped fonts. A 7.0-friendly application should allow its
  9879. users to take advantage of this improvement. Minimally, this means that users
  9880. should be able to ask for any point size up to 32,768. Many applications now let
  9881. users specify font sizes up to 127 point, but you should remove even this
  9882. limitation when running in version 7.0. In addition, your application should
  9883. allow users to increment or decrement the font size by 1 point.
  9884.  
  9885. You can use the IsOutline routine, documented in the Font Manager chapter in
  9886. this volume, to see if a particular font is an outline font. If it is, you might
  9887. wish to indicate that fact in your font size menu. For example, suppose that
  9888. your Size menu for a particular bitmapped font looks like the one in Figure 3-1.
  9889.  
  9890. ø 3.1  Size menu for a bitmapped font
  9891.  
  9892. To provide a visual indication that the selected font is an outline font that
  9893. looks good at any size, you might change the menu to look like the one in Figure
  9894. 3-2. One way to do this is by outlining all available sizes, as well as the
  9895. Other item.
  9896.  
  9897. ø 3.2  Size menu for an outline font
  9898.  
  9899. The User Interface Guidelines chapter contains additional suggestions on
  9900. incorporating outline fonts into your application.
  9901.  
  9902. _______________________________________________________________________________
  9903.  
  9904. æKY Operating…With…Virtual…Memory
  9905. æC »Operating With Virtual Memory                                 Compatibility Guidelines
  9906. _______________________________________________________________________________
  9907.  
  9908. System software version 7.0 supports virtual memory, a memory management scheme
  9909. that extends the logical address space of the machine by using part of the
  9910. available secondary storage (usually, a hard disk) to store parts of memory that
  9911. are not currently in use. When virtual memory is present, the perceived amount
  9912. of RAM can extend up to 14 megabytes on systems with 24-bit ROMs and up to 4
  9913. gigabytes on systems with 32-bit clean ROMs. Since the Operating System has more
  9914. addressable memory, your applications can ask for and receive larger blocks of
  9915. memory than they would if virtual memory were not available.
  9916.  
  9917. Virtual memory is available only on machines equipped with a memory management
  9918. unit (MMU). Currently, these machines include 68030-based machines (where the
  9919. MMU is built into the CPU) as well as 68020-based machines that contain the
  9920. 68851 Paged Memory Management Unit. You can use the Gestalt function to
  9921. determine whether virtual memory is installed. If it is, you may need to
  9922. exercise caution to ensure that the normally invisible operation of virtual
  9923. memory does not adversely affect the execution of your application. Applications
  9924. that might need to be concerned with virtual memory include those that have
  9925. critical timing requirements, execute code at interrupt time, or perform
  9926. debugging operations.
  9927.  
  9928. Note:  The vast majority of applications do not need to know whether virtual
  9929. memory is installed.  
  9930.  
  9931. One type of application that might need to know if virtual memory is operating
  9932. is a multimedia application that manages very large images or incorporates many
  9933. sounds into its presentations. Imagine that such an application wants to display
  9934. a large number of intricate color images in rapid succession, and that some of
  9935. those images are as large as a megabyte each. If virtual memory is operating, it
  9936. is very likely that parts of those images are on disk when they need to be
  9937. displayed. This means that in the middle of drawing a picture, the system has to
  9938. stop long enough to read those parts of the picture off the disk. The result is
  9939. that a noticeable delay may occur, which may be unacceptable.
  9940.  
  9941. In a case like this, you can use routines that lock the appropriate data into
  9942. RAM, so that displaying the image requires no disk access. These routines are
  9943. fully documented in the Memory Management chapter later in this volume. Other
  9944. software that may need to know about those routines includes drivers, interrupt
  9945. code, and debugging applications.
  9946.  
  9947. _______________________________________________________________________________
  9948.  
  9949. æKY Localizing…Macintosh…Programs
  9950. æC »LOCALIZING MACINTOSH PROGRAMS                                 Compatibility Guidelines
  9951. _______________________________________________________________________________
  9952.  
  9953. Localization is the process of adapting an application to a specific language
  9954. and country. By planning ahead and making localization relatively painless, 
  9955. you’ll ensure that international markets are available for your product in the
  9956. future. This section provides a brief overview of what you need to do to make it
  9957. easy to localize your application. For the complete account of writing software
  9958. that is compatible with Macintosh computers throughout the world, you should
  9959. read the TextEdit chapter and the Worldwide Software Overview later in this
  9960. volume. You should also consult the “Developing Worldwide Software” section in
  9961. the User Interface Guidelines chapter of this volume.
  9962.  
  9963. _______________________________________________________________________________
  9964.  
  9965. æKY General…Guidelines…for…Compatibility
  9966. æC »General Guidelines                                            Compatibility Guidelines
  9967. _______________________________________________________________________________
  9968.  
  9969. The key to easy localization is to store country-dependent information used by
  9970. your application as resources (rather than within the application’s code). Text
  9971. seen by the user can then be translated without modifying the code. In addition,
  9972. storing such information in resources means that your application can be adapted
  9973. for a different country simply by substituting the appropriate resources. Make
  9974. sure that at least the following kinds of information are stored in resources:
  9975.  
  9976.   •   all text, including special characters and delimiters
  9977.  
  9978.   •   menus and keyboard equivalents for menu commands (if available)
  9979.  
  9980.   •   character, word, phrase, and text translation tables
  9981.  
  9982.   •   address formats, including zip codes and phone numbers
  9983.  
  9984. When you create resources for your applications, remember the following key
  9985. points:
  9986.  
  9987.   •   text needs room to grow (up, down, and sideways)
  9988.  
  9989.   •   translated text is often 50 percent larger than the U.S. English text
  9990.  
  9991.   •   diacritical marks, widely used outside the United States, may extend up
  9992.       to the ascent line
  9993.  
  9994.   •   some system fonts contain characters that extend to both the ascent and
  9995.       descent lines
  9996.  
  9997.   •   potential grammar problems may arise from error messages, “natural”
  9998.       programming language structures, and so forth
  9999.  
  10000.   •   text location within a window should be easy to change
  10001. _______________________________________________________________________________
  10002.  
  10003. æKY Other…Localization…Tools
  10004. æC »Other Localization Tools                                      Compatibility Guidelines
  10005. _______________________________________________________________________________
  10006.  
  10007. In addition to these general guidelines, you need to be aware of a host of other
  10008. localization issues, such as differences in script systems and measurement
  10009. systems. System software version 7.0 contains updated versions of several tools
  10010. that you can use to facilitate localization of your applications—TextEdit, the
  10011. International Utilities Package, and the Script Manager.
  10012.  
  10013. Perhaps the most important localization tool is the Script Manager, which
  10014. contains routines that allow your application to function correctly with
  10015. non-Roman scripts (or writing systems). The Script Manager furnishes a standard
  10016. interface that allows installation of different script systems, maintains global
  10017. data structures, supports switching keyboards between different scripts, and
  10018. provides a central dispatcher that gives your application access to script
  10019. systems. It also contains utilities for text processing and parsing, which are
  10020. useful for applications that do a lot of text manipulation. The Script Manager
  10021. provides easy ways to translate your application into another writing system and
  10022. to coordinate with the International Utilities Package.
  10023.  
  10024. The International Utilities Package provides routines for dealing with sorting,
  10025. currency, measurement systems, and date and time formatting. These tend to vary
  10026. in some degree from script to script, language to language, and country to
  10027. country, and your application should take advantage of the Macintosh Operating
  10028. System’s ability to present this information in the correct format. It is
  10029. important that you use the routines in this package rather than the System
  10030. Utility routines contained in ROM; the ROM routines are not as accurate and 
  10031. (because they are used by the File Manager) cannot be localized for different
  10032. countries.
  10033.  
  10034. TextEdit provides routines that handle basic text formatting and editing
  10035. capabilities, such as inserting new text or scrolling text within a window. The
  10036. version of TextEdit included in system software version 7.0 contains new
  10037. features that allow it to work with different scripts. For example, TextEdit 3.0
  10038. takes advantage of the Script Manager’s handling of double-byte characters to
  10039. display scripts (such as Kanji) with improved accuracy and consistency.
  10040.  
  10041. For more information about the enhanced versions of TextEdit, see the TextEdit
  10042. chapter in this volume. For complete information on both the International
  10043. Utilities Package and the Script Manager, see the Worldwide Software Overview
  10044. chapter.
  10045.  
  10046. _______________________________________________________________________________
  10047.  
  10048. æKY Running…Macintosh…Programs…Under…A/UX
  10049. æC »RUNNING MACINTOSH PROGRAMS UNDER A/UX                         Compatibility Guidelines
  10050. _______________________________________________________________________________
  10051.  
  10052. A/UX is Apple’s version of the UNIX operating system, which provides a
  10053. multitasking and multiuser software execution environment. One of the most
  10054. distinctive features of A/UX in comparison with other implementations of the
  10055. UNIX operating system is its ability to run conforming Macintosh applications.
  10056. Within limits described later in this section, applications developed for the
  10057. Macintosh Operating System using the standard Macintosh User Interface Toolbox
  10058. routines will execute under A/UX. Figure 3-3 shows a typical screen under A/UX.
  10059.  
  10060. ø 3.3  The Macintosh User Interface Under A/UX
  10061.  
  10062. The ability to run Macintosh applications under A/UX is provided by enhancements
  10063. to the A/UX kernel and by a library of functions known as the A/UX Toolbox. The
  10064. A/UX Toolbox is a library of routines that enables a program running under A/UX
  10065. to call Macintosh Toolbox routines and native Macintosh Operating System
  10066. routines. The A/UX Toolbox provides a bridge between the Macintosh and A/UX
  10067. environments, giving you two kinds of code compatibility:
  10068.  
  10069.   •   You can execute Macintosh binary code (applications compiled in the
  10070.       Macintosh environment) under A/UX, within the current limitations of the
  10071.       A/UX Toolbox.
  10072.  
  10073.   •   You can write common source code that can be separately built (that is,
  10074.       compiled and linked) into executable code for both environments.
  10075.  
  10076. The A/UX Toolbox operates transparently to the user and to the application
  10077. developer. This means that (subject once again to qualifications detailed later)
  10078. your applications developed for the Macintosh Operating System should execute
  10079. under the A/UX operating system.
  10080.  
  10081. The version of A/UX currently available is A/UX Release 2.0, which greatly
  10082. extends the capabilities of earlier versions. Release 2.0 supports more managers
  10083. and drivers than previous versions, thereby increasing the level of
  10084. compatibility with Macintosh applications. There is now transparent access to
  10085. Macintosh file systems from within A/UX, so users no longer have to transfer
  10086. files between the two systems manually.
  10087.  
  10088. This section briefly explains how the A/UX Toolbox works and then provides
  10089. details on writing Macintosh applications that execute under the A/UX operating
  10090. system. A/UX Release 2.0 provides such a high level of compatibility with
  10091. Macintosh applications that your existing applications may very well run under 
  10092. A/UX with no changes whatsoever. To run successfully under A/UX Release 2.0,
  10093. your application should
  10094.  
  10095.   •   be compatible with MultiFinder
  10096.  
  10097.   •   be 32-bit clean (that is, operate in an environment where all 32 bits of
  10098.       a handle or pointer are significant in determining memory addresses)
  10099.  
  10100.   •   use the Gestalt Manager to determine whether the appropriate versions of
  10101.       managers are present in the current operating environment
  10102.  
  10103.   •   avoid reading or writing low-memory global variables
  10104.  
  10105. In general, applications that conform to the interfaces documented in Inside
  10106. Macintosh, are MultiFinder-aware, do not rely on low-memory global variables,
  10107. and heed the various guidelines presented in “About Compatibility” should
  10108. operate under A/UX.
  10109.  
  10110. _______________________________________________________________________________
  10111.  
  10112. æKY How…the…A/UX…Toolbox…Works
  10113. æC »How the A/UX Toolbox Works                                    Compatibility Guidelines
  10114. _______________________________________________________________________________
  10115.  
  10116. The primary function of the A/UX Toolbox is to make available to programs
  10117. running under A/UX the standard Macintosh support code described in Inside
  10118. Macintosh. Most of the support code consists of routines built into the
  10119. Macintosh ROM.
  10120.  
  10121. The ROM routines fall into two categories, User Interface Toolbox routines and
  10122. Macintosh Operating System routines. The A/UX Toolbox uses one of two strategies
  10123. for supporting a Macintosh ROM call, depending on whether the call is to the
  10124. User Interface Toolbox or to the native Macintosh Operating System.
  10125.  
  10126. When an A/UX Toolbox application calls one of the Macintosh User Interface
  10127. Toolbox routines, the A/UX Toolbox intercepts the call and, if necessary,
  10128. translates the parameters into a form usable by the ROM. After the A/UX Toolbox
  10129. performs the translation, it invokes the ROM code that would be used in the
  10130. native Macintosh environment.
  10131.  
  10132. When an A/UX Toolbox application calls one of the Macintosh Operating System
  10133. routines, the A/UX Toolbox diverts the call to a substitute routine in its own
  10134. library. The A/UX Toolbox Operating System routines call the standard A/UX
  10135. libraries to perform the A/UX equivalents of the Macintosh Operating System
  10136. functions. The Macintosh Operating System ROM code is never used under A/UX.
  10137. Note that some of the built-in User Interface Toolbox routines generate calls to
  10138. the Macintosh Operating System routines; these calls are also intercepted by the
  10139. A/UX Toolbox and diverted to routines in its own library.
  10140.  
  10141. Figure 3-4 illustrates how the two elements of the A/UX Toolbox library interact
  10142. with the application and the ROM code.
  10143.  
  10144. ø 3.4  Interactions among applications, the A/UX Toolbox, and ROM code
  10145.  
  10146. _______________________________________________________________________________
  10147.  
  10148. æKY Using…the…A/UX…Toolbox
  10149. æC »Using the A/UX Toolbox                                        Compatibility Guidelines
  10150. _______________________________________________________________________________
  10151.  
  10152. The primary limitation on Macintosh applications running under A/UX is that the
  10153. A/UX Toolbox does not currently support all managers and drivers. Table 3-2
  10154. summarizes the status of various ROM libraries in A/UX Release 2.0.
  10155.  
  10156. Table 3-2.  Status of User Interface Toolbox and Macintosh Operating System
  10157. libraries in the A/UX Toolbox 
  10158.  
  10159. ROM Library                               Implementation
  10160.  
  10161. Alias Manager                             None
  10162. Apple Desktop Bus                         None
  10163. Binary-Decimal Conversion Package         Full
  10164. Color Manager                             Full
  10165. Color Picker Package                      Full
  10166. Color QuickDraw                           Full
  10167. Control Manager                           Full
  10168. Database Access Manager                   None
  10169. Deferred Task Manager                     None
  10170. Desk Manager                              Full
  10171. Device Manager                            Full
  10172. Dialog Manager                            Full
  10173. Disk Driver                               Full
  10174. Disk Initialization Package               Full
  10175. Edition Manager                           None
  10176. Event Manager, Operating System           Partial
  10177. Event Manager, Toolbox                    Full*
  10178. File Manager                              Full
  10179. Floating Point Arithmetic                
  10180.   and Transcendental Functions Packages   Full*
  10181. Font Manager                              Full
  10182. Gestalt Manager                           Full
  10183. Help Manager                              None
  10184. International Utilities Package           Full
  10185. List Manager Package                      Full
  10186. Memory Manager                            Full
  10187. Menu Manager                              Full
  10188. Notification Manager                      Full
  10189. Package Manager                           Full
  10190. Palette Manager                           Full
  10191. Power Manager                             None
  10192. PPC Toolbox                               None
  10193. Printing Manager                          Full
  10194. QuickDraw                                 Full
  10195. Resource Manager                          Full
  10196. Scrap Manager                             Full
  10197. Script Manager                            Full
  10198. SCSI Manager                              None
  10199. Segment Loader                            Partial
  10200. Serial Driver                             Full
  10201. Shutdown Manager                          Full*
  10202. Slot Manager                              Full
  10203. Sound Manager                             Full
  10204. Startup Manager                           Full
  10205. Standard File Package                     Full
  10206. System Error Handler                      Full*
  10207. TextEdit                                  Full
  10208. Time Manager                              Full*
  10209. Utilities, Operating System               Partial
  10210. Utilities, Toolbox                        Full
  10211. Vertical Retrace Manager                  Partial
  10212. Window Manager                            Full
  10213.  
  10214. Note that when A/UX Release 2.0 implements a particular manager or driver, the
  10215. version of that manager or driver may not be the same as the version available
  10216. in the Macintosh Operating System. This means that, whenever possible, you
  10217. should use Gestalt to check for the existence of the particular features your
  10218. application needs. In managers or drivers marked with an asterisk (*), all calls
  10219. are implemented under A/UX, but the behavior is not identical to that in the
  10220. Macintosh Operating System. See the publication A/UX Toolbox: Macintosh ROM
  10221. Interface for complete details on the implementation of these managers and
  10222. drivers.
  10223.  
  10224. _______________________________________________________________________________
  10225.  
  10226. æKY A/UX…Compatibility…Guidelines
  10227. æC »A/UX Compatibility Guidelines                                 Compatibility Guidelines
  10228. _______________________________________________________________________________
  10229.  
  10230. The A/UX Toolbox has been designed to allow as many Macintosh applications as
  10231. possible to execute under the A/UX operating system. Because of profound
  10232. differences between the two environments, however, it is possible that some
  10233. applications may not execute correctly under A/UX. By following these
  10234. guidelines, you can help ensure that your Macintosh applications run under A/UX.
  10235.  
  10236.   •   Make certain that your application is MultiFinder-friendly. MultiFinder
  10237.       is a standard part of A/UX Release 2.0, just as it is in system software
  10238.       version 7.0. Your application should include a 'SIZE' resource and call
  10239.       WaitNextEvent in its main event loop. Note that the version of
  10240.       MultiFinder included with A/UX Release 2.0 is functionally equivalent to
  10241.       the version of MultiFinder released with system software version 6.0.5,
  10242.       but has been customized for use under A/UX.
  10243.  
  10244.   •   Always use the available managers and drivers to manipulate hardware
  10245.       devices. In the Macintosh Operating System, individual processes and the
  10246.       various libraries can have much more control over the system than under
  10247.       A/UX, where the kernel manages all interaction between processes and the
  10248.       underlying hardware. In particular, do not attempt to read data from or
  10249.       write data to any of the memory-mapped hardware available on a Macintosh
  10250.       computer.
  10251.  
  10252.   •   Avoid relying on any of the low-memory global variables. Not all of them
  10253.       are available under A/UX.
  10254.  
  10255.   •   Make certain that your application is 32-bit clean (that is, it operates
  10256.       in an environment where all 32 bits of a handle or pointer are
  10257.       significant in determining memory addresses).
  10258.  
  10259.   •   Use the Gestalt Manager to determine which versions of managers and
  10260.       drivers are present in the current operating environment before relying
  10261.       on features that are not common to all released versions. Generally, the
  10262.       versions of managers available under A/UX Release 2.0 are the same as
  10263.       those versions included in Macintosh system software version 6.0.5.
  10264.  
  10265. Finally, your application should conform to the programming interfaces described
  10266. in Inside Macintosh and should follow the basic compatibility guidelines
  10267. presented in “About Compatibility” earlier in this chapter.
  10268.  
  10269. _______________________________________________________________________________
  10270.  
  10271. æKY About…the…Gestalt…Manager
  10272. æC »ABOUT THE GESTALT MANAGER                                     Compatibility Guidelines
  10273. _______________________________________________________________________________
  10274.  
  10275. The Macintosh family of computers has grown tremendously in the past several
  10276. years, and it is likely to grow in the future. Macintosh software now runs on a
  10277. number of different processors, some of which are accompanied by floating-point
  10278. coprocessors or memory management units. In addition, the installed versions of
  10279. the system software, drivers, and QuickDraw routines may vary from machine to
  10280. machine. To ensure that your applications are maximally compatible with existing
  10281. and future versions of the Macintosh, you should keep references to specific
  10282. software and hardware features to a minimum. In general, applications should
  10283. communicate with the system software and hardware through the available managers
  10284. and device drivers. If, however, it is necessary or useful for your applications
  10285. to take advantage of software or hardware components that may not be present on
  10286. all Macintosh computers, then you need some method of determining whether those
  10287. components are available. The Gestalt Manager serves this need by allowing you
  10288. to get information about the operating environment in a simple and efficient
  10289. manner.
  10290.  
  10291. System software version 7.0 is a major software release that affects the entire
  10292. Macintosh line of computers, spanning different CPUs, different versions of ROM,
  10293. and machines with a variety of hardware and software configurations. Version 7.0
  10294. introduces several new managers and makes significant changes to many existing
  10295. managers. To take advantage of new version 7.0 features, and to run on as many
  10296. machines as possible, it is more important than ever before to determine the
  10297. software and hardware components available in a particular operating
  10298. environment.
  10299.  
  10300. To deal with this increasingly complex situation, system software version 7.0
  10301. includes the Gestalt Manager. This manager includes the Gestalt function, which
  10302. is a replacement for both the SysEnvirons function and the Environs procedure.
  10303. The Gestalt function gives applications the ability to determine information
  10304. about a large number of machine-dependent features. You can use the Gestalt
  10305. function to find the following sorts of information about the hardware
  10306. configuration and operating environment of the machine your application is
  10307. executing on:
  10308.  
  10309.   •   the type of machine
  10310.   •   the version of the System file currently running
  10311.   •   the type of CPU
  10312.   •   the type of keyboard attached to the machine
  10313.   •   the type of floating-point processing unit (FPU), if any
  10314.   •   the type of memory management unit (MMU), if any
  10315.   •   the size of available RAM
  10316.   •   the amount of available virtual memory
  10317.   •   the versions of various drivers and managers
  10318.   •   the features of various drivers and managers
  10319.   •   the version of QuickDraw currently present
  10320.   •   whether the A/UX operating system is running or not
  10321.  
  10322. How your application uses the resulting information depends on what your
  10323. application needs to accomplish. For example, in a case where critical hardware
  10324. features are not available, your application might display an alert box to
  10325. notify the user that the required hardware is missing and then terminate. Or, if
  10326. your application has determined that Color QuickDraw is available, it could
  10327. execute alternate code to take advantage of the expanded capabilities of that
  10328. software.
  10329.  
  10330. Associated with the Gestalt function are two other functions—one that allows an
  10331. application to register new features with Gestalt and another that allows an
  10332. application to change the function used by Gestalt to retrieve a particular
  10333. piece of information. These two functions make it easy for your application to
  10334. announce its presence to other applications, in case they wish to alter their
  10335. actions in view of the presence of your application. For example, a macro
  10336. utility that intercepts sequences of keyboard presses and translates them into
  10337. other sequences can register itself with Gestalt at system initialization time;
  10338. afterward, other applications can call Gestalt to determine if that utility is
  10339. present. In this way, Gestalt can act as a central clearinghouse for information
  10340. on the available hardware and software features of the operating environment,
  10341. including any third-party applications that register themselves with Gestalt.
  10342. Gestalt therefore provides a further means of cooperation and awareness among
  10343. applications executing in the version 7.0 environment.
  10344.  
  10345. Although the Gestalt function can provide your application with most of the
  10346. basic information it needs about particular software or hardware features, you
  10347. may still need to call other routines to determine more specific features. For
  10348. example, if you need to determine the resolution of the Macintosh screen, you
  10349. can use the Toolbox Utility procedure ScreenRes. (See the Toolbox Utilities
  10350. chapter of Inside Macintosh, Volume I, for a description of this procedure.)
  10351. The Gestalt function replaces both the Environs procedure and the current
  10352. implementation of the SysEnvirons function as the standard means of determining
  10353. specific aspects of the operating environment. The Gestalt Manager is simpler to
  10354. use and provides more information than either of those routines. Applications
  10355. that use SysEnvirons still execute correctly in system software version 7.0 (the
  10356. SysEnvirons function calls the Gestalt function).
  10357.  
  10358. Use of the Environs procedure is no longer recommended, because it encourages
  10359. you to think in terms of ROM versions, not in term of features that may be
  10360. available. The Gestalt Manager can also provide information such as ROM version
  10361. and size, but you should not write applications that infer the presence of
  10362. particular software or hardware features on the basis of that information. When
  10363. you need to know whether a particular feature is present, you should request
  10364. information about it directly, using the appropriate Gestalt selector.
  10365.  
  10366. Although you can still call the SysEnvirons function, the Gestalt Manager is
  10367. simpler and more efficient, and is the recommended way to get information about
  10368. the operating environment. SysEnvirons returns a pointer to a system environment
  10369. record containing nine different pieces of information. Gestalt returns only the
  10370. information requested by use of a specific selector code parameter. In most
  10371. cases, your application really needs only a part of what is contained in the
  10372. system environment record. With Gestalt, your application can request only the
  10373. information it needs.
  10374.  
  10375. _______________________________________________________________________________
  10376.  
  10377. æKY Using…the…Gestalt…Manager
  10378. æC »USING THE GESTALT MANAGER                                     Compatibility Guidelines
  10379. _______________________________________________________________________________
  10380.  
  10381. The Gestalt Manager includes three functions—Gestalt, NewGestalt, and
  10382. ReplaceGestalt. You can use the Gestalt function to obtain information about
  10383. software or hardware components available on the current machine. You can use
  10384. NewGestalt to register new software modules (such as drivers and patches) with
  10385. the Operating System. Use ReplaceGestalt to replace the function associated with
  10386. a particular selector code by some other function.
  10387.  
  10388. Note:  Most applications do not need to use either NewGestalt or ReplaceGestalt.
  10389.  
  10390. _______________________________________________________________________________
  10391.  
  10392. æKY Determining…Features…of…the…Operating…Environment
  10393. æC »Determining Features of the Operating Environment             Compatibility Guidelines
  10394. _______________________________________________________________________________
  10395.  
  10396. When your application needs information about a specific software or hardware
  10397. feature that can be provided by the Gestalt function, your application can pass
  10398. Gestalt a selector code (or selector) as one of the parameters. The selector
  10399. code is simply an indication of what information your application currently
  10400. needs. There are two types of selector codes—predefined selector codes that are
  10401. always recognized by Gestalt, and application-defined selector codes that
  10402. applications may register with Gestalt by calling the NewGestalt function.
  10403.  
  10404. If Gestalt can determine the requested information, it returns that information
  10405. in its second parameter, known as the response parameter. If Gestalt cannot
  10406. obtain the desired information, it returns a result code indicating the cause of
  10407. the error, and the value of the response parameter is undefined. You should
  10408. always check the result code returned by Gestalt to make sure that the response
  10409. parameter contains meaningful information.
  10410.  
  10411. Note:  When passed one of the predefined selector codes, Gestalt does not move
  10412. or purge memory and therefore may be called at any time, even at interrupt time.
  10413. However, selector functions associated with application-defined selector codes
  10414. may move or purge memory, and applications can alter Gestalt’s predefined
  10415. selector functions. As a result, it is safest to assume that Gestalt might
  10416. always move or purge memory. The NewGestalt function may move memory and should
  10417. not be called at interrupt time.
  10418.  
  10419. There are two types of predefined selector codes: codes that return information
  10420. that your application can use to guide its actions (known as environmental
  10421. selectors), and codes that provide information only and should never be used as
  10422. an indication of some feature’s existence (known as informational selectors).
  10423.  
  10424. It is particularly important that you understand the difference between
  10425. environmental and informational selectors. The response returned by Gestalt when
  10426. it is passed an informational selector is for your (or the user’s) edification
  10427. only and should never be used by your application as a means of determining
  10428. whether some specific software or hardware feature is available. For example,
  10429. you can use Gestalt to determine the version of the ROM installed on a
  10430. particular machine, but you should never use this information to guide any of
  10431. your application’s actions. Routines you expect to be in ROM may actually be in
  10432. RAM; hence, you cannot determine that some routine usually found in ROM is not
  10433. present simply by looking at the ROM version. Also, routines contained in ROM
  10434. may have been patched by the system at startup time, in which case the system
  10435. might not have the features that you think it has on the basis of the reported
  10436. ROM version. Similar remarks apply to other informational selectors such as ROM
  10437. size, machine type, and System file version.
  10438.  
  10439. You can use the following environmental selectors to determine information about
  10440. the operating environment.
  10441.  
  10442. CONST
  10443. gestaltVersion                = 'vers';  {Gestalt version}
  10444. gestaltAddressingModeAttr     = 'addr';  {addressing mode attributes}
  10445. gestaltAliasMgrAttr           = 'alis';  {Alias Mgr attributes}
  10446. gestaltAppleTalkVersion       = 'atlk';  {AppleTalk version}
  10447. gestaltAUXVersion             = 'a/ux';  {A/UX version if present}
  10448. gestaltCTBVersion             = 'ctbv';  {Comm Toolbox version}
  10449. gestaltDBAccessMgrAttr        = 'dbac';  {Database Access Mgr attrs}
  10450. gestaltEditionMgrAttr         = 'edtn';  {Edition Mgr attributes}
  10451. gestaltAppleEventsAttr        = 'evnt';  {AppleEvents attributes}
  10452. gestaltFolderMgrAttr          = 'fold';  {Folder Mgr attributes}
  10453. gestaltFontMgrAttr            = 'font';  {Font Mgr attributes}
  10454. gestaltFPUType                = 'fpu ';  {FPU type}
  10455. gestaltHardwareAttr           = 'hdwr';  {hardware attributes}
  10456. gestaltHelpMgrAttr            = 'help';  {Help Mgr attributes}
  10457. gestaltKeyboardType           = 'kbd ';  {keyboard type}
  10458. gestaltLowMemorySize          = 'lmem';  {low-memory area size}
  10459. gestaltLogicalRAMSize         = 'lram';  {logical RAM size}
  10460. gestaltMiscAttr               = 'misc';  {miscellaneous attributes}
  10461. gestaltMMUType                = 'mmu ';  {MMU type}
  10462. gestaltNotificationMgrAttr    = 'nmgr';  {Notification Mgr attrs}
  10463. gestaltOSAttr                 = 'os  ';  {O/S attributes}
  10464. gestaltLogicalPageSize        = 'pgsz';  {logical page size}
  10465. gestaltPPCToolboxAttr         = 'ppc ';  {PPC Toolbox attributes}
  10466. gestaltPowerMgrAttr           = 'powr';  {Power Mgr attributes}
  10467. gestaltProcessorType          = 'proc';  {processor type}
  10468. gestaltParityAttr             = 'prty';  {parity attributes}
  10469. gestaltQuickdrawVersion       = 'qd  ';  {QuickDraw version}
  10470. gestaltPhysicalRAMSize        = 'ram ';  {physical RAM size}
  10471. gestaltResourceMgrAttr        = 'rsrc';  {Resource Mgr attributes}
  10472. gestaltScriptMgrVersion       = 'scri';  {Script Mgr version}
  10473. gestaltScriptCount            = 'scr#';  {# of active script systems}
  10474. gestaltSoundAttr              = 'snd ';  {sound attributes}
  10475. gestaltTextEditVersion        = 'te  ';  {TextEdit version}
  10476. gestaltTimeMgrVersion         = 'tmgr';  {Time Mgr version}
  10477. gestaltVMAttr                 = 'vm  ';  {virtual memory attributes}
  10478.  
  10479. The following informational selectors are provided for informational purposes
  10480. only. You can display the information returned when using these selectors, but
  10481. you should never use this information as an indication of what software features
  10482. or hardware may be available.
  10483.  
  10484. CONST
  10485. gestaltMachineType            = 'mach';  {machine type}
  10486. gestaltROMSize                = 'rom ';  {ROM size}
  10487. gestaltROMVersion             = 'romv';  {ROM version}
  10488. gestaltSystemVersion          = 'sysv';  {System file version}
  10489.  
  10490. “Interpreting Gestalt Responses” later in this chapter provides the exact
  10491. meaning of each of these selectors and of the values returned by Gestalt in each
  10492. case.
  10493.  
  10494. _______________________________________________________________________________
  10495.  
  10496. æKY Determining…Whether…Gestalt…Is…Available
  10497. æC »Determining Whether Gestalt Is Available                      Compatibility Guidelines
  10498. _______________________________________________________________________________
  10499.  
  10500. Because the Gestalt Manager currently exists only in system software versions
  10501. 6.0.4 and later (and in ROM on the Macintosh IIci and Portable), you should make
  10502. certain that it is actually available before attempting to call it. You can do
  10503. this by using the TrapAvailable function defined above in “Determining Whether a
  10504. Trap Is Available.” Listing 3-3 uses that function to determine whether the
  10505. Gestalt Manager is available.
  10506.  
  10507. Note:  If you are using the MPW development system version 3.2 or later, then
  10508. you do not need to perform this check, because that system provides glue
  10509. routines that allow you to call Gestalt even if it is not in ROM or in the
  10510. System file. However, if you are programming in assembly language, this glue is
  10511. not provided (and you still need to check that Gestalt is available before
  10512. calling it).  
  10513.  
  10514. Listing 3-3.  Determining whether Gestalt is available
  10515.  
  10516. FUNCTION GestaltAvailable: Boolean;
  10517. CONST
  10518.   _Gestalt   =  $A1AD;
  10519. BEGIN
  10520.   GestaltAvailable := TrapAvailable(_Gestalt);
  10521. END;
  10522.  
  10523. If you need to know at several different places in your application whether
  10524. Gestalt is available, it may be more efficient to define a global Boolean
  10525. variable that you can test before calling Gestalt. Listing 3-4 illustrates how
  10526. to do this. Once again, this code uses the TrapAvailable function defined
  10527. earlier.
  10528.  
  10529. Listing 3-4.  Using Gestalt to determine the Time Manager version
  10530.  
  10531. VAR
  10532.   hasGestalt:  Boolean;  {true if Gestalt is implemented}
  10533.  
  10534. hasGestalt := TrapAvailable(_Gestalt);
  10535.   .
  10536.   .
  10537.   .
  10538.  
  10539. IF hasGestalt THEN BEGIN
  10540.   myErr := Gestalt(gestaltTimeMgrVersion, myFeature);
  10541.   IF myErr <> noErr THEN
  10542.     DoError(myErr);
  10543. END;
  10544.  
  10545. This sample code returns (in the myFeature variable) the version of the Time
  10546. Manager available on the current machine. Before using that information, 
  10547. however, you should test the result code to make sure that Gestalt was able to
  10548. determine the requested information.
  10549.  
  10550. _______________________________________________________________________________
  10551.  
  10552. æKY Interpreting…Gestalt…Responses
  10553. æC »Interpreting Gestalt Responses                                Compatibility Guidelines
  10554. _______________________________________________________________________________
  10555.  
  10556. When your application calls Gestalt to get information about the operating
  10557. environment, the meaning of the value that Gestalt returns in the response
  10558. parameter depends on the selector code with which it was called. For example, a
  10559. call to Gestalt using the gestaltTimeMgrVersion selector returns a version code
  10560. in the low-order byte of the response parameter. In this case, a returned value
  10561. of 3 indicates that the extended Time Manager is available.
  10562.  
  10563. In almost all cases, the last few characters in the selector’s symbolic name
  10564. form a suffix that indicates what type of value you can expect Gestalt to
  10565. return. For example, if the final characters in a Gestalt selector are Addr,
  10566. then Gestalt returns an address in the response parameter. The following list
  10567. shows the meaningful suffixes.
  10568.  
  10569. Suffix  Meaning
  10570.  
  10571. Addr    The returned value is an address.
  10572.  
  10573. Attr    The returned value is a range of bits, the meaning of which must be
  10574.         determined by comparison with a list of constants. Note that bit 0 is
  10575.         the least significant bit of the long word.
  10576.  
  10577. Count   The returned value is a number indicating how many of the indicated type
  10578.         of item exist.
  10579.  
  10580. Size    The returned value is a size. Sizes reported by Gestalt are usually in 
  10581.         bytes.
  10582.  
  10583. Type    The returned value is an index describing a particular type of feature.
  10584.  
  10585. Version The returned value is a version number. Implied decimal points may
  10586.         separate digits of the returned value. For example, a value of $0603
  10587.         returned in response to the gestaltSystemVersion selector indicates 
  10588.         that system software version 6.0.3 is present.
  10589.  
  10590. Selectors that have the suffix Attr deserve special attention; they cause
  10591. Gestalt to return a bit field that your application must interpret in order to
  10592. determine whether a desired feature is present. For example, the gestaltOSAttr
  10593. selector requests information about a number of Operating System features. To
  10594. determine whether a particular Operating System feature is available, you need
  10595. to read the appropriate bit in the response parameter, as Listing 3-5
  10596. illustrates.
  10597.  
  10598. Listing 3-5.  Interpreting a bit field response
  10599.  
  10600. VAR
  10601.   myBit:  Integer;
  10602.   myFeature:  LongInt;
  10603.   myErr:  Integer;
  10604.  
  10605. IF hasGestalt THEN BEGIN
  10606.   myErr := Gestalt(gestaltOSAttr, myFeature);
  10607.   IF myErr <> noErr THEN
  10608.     DoError(myErr)
  10609.   ELSE BEGIN
  10610.     myBit := gestaltTempMemSupport;
  10611.     IF BTst(myFeature, 31-myBit) = TRUE THEN
  10612.       WriteLn('temporary memory support available')
  10613.     ELSE
  10614.       WriteLn('temporary memory support not available');
  10615.   END;
  10616. END;
  10617.  
  10618. This code uses the MPW function BTst to determine if the appropriate bit in
  10619. Gestalt’s response is equal to 1. Your development system may have other ways of
  10620. testing the appropriate bit.
  10621.  
  10622. _______________________________________________________________________________
  10623.  
  10624. æKY Interpreting…Responses…to…Environmental…Selectors
  10625. æC »Interpreting Responses to Environmental Selectors             Compatibility Guidelines
  10626. _______________________________________________________________________________
  10627.  
  10628. Gestalt returns one of the following responses when passed a predefined
  10629. environmental selector.
  10630.  
  10631. gestaltVersion
  10632.  
  10633. Returns the version of Gestalt. The current version is 1, corresponding to a
  10634. returned value of $0001.
  10635.  
  10636. gestaltAddressingModeAttr
  10637.  
  10638. Returns information about the current addressing.
  10639.  
  10640. CONST
  10641. gestalt32BitAddressing  = 0;
  10642. gestalt32BitSysZone     = 1;
  10643. gestalt32BitCapable     = 2;
  10644.  
  10645. The gestalt32BitAddressing attribute indicates that the machine started up with
  10646. 32-bit addressing. The gestalt32BitSysZone attribute indicates that the system
  10647. heap has 32-bit clean block headers (regardless of the type of addressing the
  10648. machine started up in). See the Memory Management chapter for more information
  10649. about 32-bit addressing.
  10650.  
  10651. gestaltAliasMgrAttr
  10652.  
  10653. Returns information about the Alias Manager.
  10654.  
  10655. CONST
  10656. gestaltAliasMgrPresent  = 0;
  10657.  
  10658. gestaltAppleTalkVersion
  10659.  
  10660. Returns the version number of the AppleTalk driver currently installed. In
  10661. particular, it returns the version number of the MPP driver. The version number
  10662. is placed into the low-order byte of the result, so you should ignore the three
  10663. high-order bytes of the result. If an AppleTalk driver is not currently open,
  10664. the response parameter is 0. The driver will not be opened until the user
  10665. requests a network service (such as Chooser).
  10666.  
  10667. gestaltAUXVersion
  10668.  
  10669. Returns the version of A/UX if it is currently executing. The result is placed
  10670. into the lower word of the response parameter. If A/UX is not executing, Gestalt
  10671. returns gestaltUnknownErr.
  10672.  
  10673. gestaltCTBVersion
  10674.  
  10675. Returns the version number of the Communications Toolbox.
  10676.  
  10677. gestaltDBAccessMgrAttr
  10678.  
  10679. Returns information about the Database Access Manager.
  10680.  
  10681. CONST
  10682. gestaltDBAccessMgrPresent  = 0;
  10683.  
  10684. gestaltEditionMgrAttr
  10685.  
  10686. Returns information about the Edition Manager.
  10687.  
  10688. CONST
  10689. gestaltEditionMgrPresent  = 0;
  10690.  
  10691. gestaltAppleEventsAttr
  10692.  
  10693. Returns information about AppleEvents.
  10694.  
  10695. CONST
  10696. gestaltAppleEventsPresent  = 0;
  10697.  
  10698. gestaltFolderMgrAttr
  10699.  
  10700. Returns information about the Folder Manager.
  10701.  
  10702. CONST
  10703. gestaltFolderMgrPresent  = 0;
  10704.  
  10705. gestaltFontMgrAttr
  10706.  
  10707. Returns information about the Font Manager.
  10708.  
  10709. CONST
  10710. gestaltOutlineFonts  = 0;
  10711.  
  10712. gestaltFPUType
  10713.  
  10714. Returns a value that indicates the type of floating-point coprocessor currently
  10715. installed, if any.
  10716.  
  10717. CONST
  10718. gestaltNoFPU          = 0;
  10719. gestalt68881          = 1;
  10720. gestalt68882          = 2;
  10721.  
  10722. gestaltHardwareAttr
  10723.  
  10724. Returns information about the hardware configuration of the machine.
  10725.  
  10726. CONST
  10727. gestaltHasVIA1       = 0;
  10728. gestaltHasVIA2       = 1;
  10729. gestaltHasASC        = 3;
  10730. gestaltHasSCC        = 4;
  10731. gestaltHasSCSI       = 7;
  10732.  
  10733. gestaltHelpMgrAttr
  10734.  
  10735. Returns information about the Help Manager.
  10736.  
  10737. CONST
  10738. gestaltHelpMgrPresent  = 0;
  10739.  
  10740. gestaltKeyboardType
  10741.  
  10742. Returns a value that indicates the type of keyboard that is currently attached
  10743. to the system.
  10744.  
  10745. CONST
  10746. gestaltMacKbd          = 1;
  10747. gestaltMacAndPad       = 2;
  10748. gestaltMacPlusKbd      = 3;
  10749. gestaltExtADBKbd       = 4;
  10750. gestaltStdADBKbd       = 5;
  10751. gestaltPrtblADBKbd     = 6;
  10752. gestaltPrtblISOKbd     = 7;
  10753. gestaltStdISOADBKbd    = 8;
  10754. gestaltExtISOADBKbd    = 9;
  10755.  
  10756. If the Apple Desktop Bus™ is in use, there may be multiple keyboards or other
  10757. ADB devices attached to the machine. Gestalt returns the type of the keyboard on
  10758. which the last keystroke occurred.
  10759.  
  10760. gestaltLowMemorySize
  10761.  
  10762. Returns the size (in bytes) of the low-memory area. The low-memory area is used
  10763. for vectors, global variables, and dispatch tables.
  10764.  
  10765. gestaltLogicalRAMSize
  10766.  
  10767. Returns the amount of logical memory available. This value is the same as that
  10768. returned by gestaltPhysicalRAMSize when virtual memory is not installed. On some
  10769. machines, however, this value might be less than the value returned by
  10770. gestaltPhysicalRAMSize, because some RAM may be used by the video display and
  10771. the Operating System.
  10772.  
  10773. gestaltMiscAttr
  10774.  
  10775. Returns information about miscellaneous pieces of the Operating System or
  10776. hardware configuration. Currently only one value is returned.
  10777.  
  10778. CONST
  10779. gestaltScrollingThrottle  = 0;
  10780.  
  10781. gestaltMMUType
  10782.  
  10783. Returns a value that indicates the type of MMU currently installed, if any.
  10784.  
  10785. CONST
  10786.  
  10787. gestaltNoMMU      = 0;
  10788. gestaltAMU        = 1;
  10789. gestalt68851      = 2;
  10790. gestalt68030MMU   = 3;
  10791.  
  10792. gestaltNotificationMgrAttr
  10793.  
  10794. Returns information about the Notification Manager.
  10795.  
  10796. CONST
  10797. gestaltNotificationMgrPresent  = 0;
  10798.  
  10799. gestaltOSAttr
  10800.  
  10801. Returns general information about the Operating System, such as whether
  10802. temporary memory handles are real handles. The low-order bits of the response
  10803. parameter are interpreted as bit flags. A flag is set to 1 to indicate that the
  10804. corresponding feature is available. Currently the following bits are
  10805. significant:
  10806.  
  10807. CONST
  10808. gestaltSysZoneGrowable     = 0;
  10809. gestaltLaunchCanReturn     = 1;
  10810. gestaltLaunchFullFileSpec  = 2;
  10811. gestaltLaunchControl       = 3;
  10812. gestaltTempMemSupport      = 4;
  10813. gestaltRealTempMemory      = 5;
  10814. gestaltTempMemTracked      = 6;
  10815. gestaltIPCSupport          = 7;
  10816. gestaltSysDebuggerSupport  = 8;
  10817.  
  10818. See the Memory Management chapter in this volume for a full explanation of the
  10819. temporary memory features and the Process Management chapter for a full
  10820. explanation of the launch control features.
  10821.  
  10822. gestaltLogicalPageSize
  10823.  
  10824. Returns the logical page size. This value is an unknown on 68000-based machines,
  10825. since such machines do not have logical pages. On those machines, Gestalt
  10826. returns an error.
  10827.  
  10828. gestaltPowerMgrAttr
  10829.  
  10830. Returns information about the Power Manager, if present.
  10831.  
  10832. CONST
  10833. gestaltPMgrExists   = 0;
  10834. gestaltPMgrCPUIdle  = 1;
  10835. gestaltPMgrSCC      = 2;
  10836. gestaltPMgrSound    = 3;
  10837.  
  10838. gestaltPPCToolboxAttr
  10839.  
  10840. Returns information about the capabilities of the PPC Toolbox.
  10841.  
  10842. CONST
  10843. gestaltPPCToolboxPresent  = 0;
  10844. gestaltPPCRealTime        = 1;
  10845.  
  10846. gestaltProcessorType
  10847.  
  10848. Returns a value that indicates the type of processor that is currently running.
  10849.  
  10850. CONST
  10851. gestalt68000  = 1;
  10852. gestalt68010  = 2;
  10853. gestalt68020  = 3;
  10854. gestalt68030  = 4;
  10855.  
  10856. gestaltParityAttr
  10857.  
  10858. Returns information about the parity-checking abilities of the machine.
  10859.  
  10860. CONST
  10861. gestaltHasParityCapability  = 0;
  10862. gestaltParityEnabled        = 1;
  10863.  
  10864. Note that parity is not considered to be enabled unless all installed memory is
  10865. parity RAM.
  10866.  
  10867. gestaltQuickdrawVersion
  10868.  
  10869. Returns a 2-byte value indicating the version of QuickDraw currently present.
  10870. The high-order byte of that number represents the major revision number, and the
  10871. low-order byte represents the minor revision number. For example, the Macintosh
  10872. IIci contains QuickDraw version 2.01 in ROM; on that machine, Gestalt returns
  10873. the value $0201.
  10874.  
  10875. CONST
  10876. gestaltOriginalQD  = $000;
  10877. gestalt8BitQD      = $100;
  10878. gestalt32BitQD     = $200;
  10879.  
  10880. Values having a major revision number of 1 and 2 indicate that Color QuickDraw
  10881. is available, in either the 8-bit or 32-bit version. These results do not,
  10882. however, indicate whether a color monitor is attached to the system. You need to
  10883. use high-level QuickDraw routines to obtain that information.
  10884.  
  10885. gestaltPhysicalRAMSize
  10886.  
  10887. Returns the number of bytes of physical RAM currently installed.
  10888.  
  10889. gestaltResourceMgrAttr
  10890.  
  10891. Returns information about the capabilities of the Resource Manager.
  10892.  
  10893. CONST
  10894. gestaltPartialRsrcsExist  = 0;
  10895. gestaltDecompression      = 1;
  10896.  
  10897. gestaltScriptMgrVersion
  10898.  
  10899. Returns the version number of the Script Manager.
  10900.  
  10901. gestaltScriptCount
  10902.  
  10903. Returns the number of scripts currently active.
  10904.  
  10905. gestaltSoundAttr
  10906.  
  10907. Returns information about the sound capabilities of the machine.
  10908.  
  10909. CONST
  10910. gestaltStereoCapability  = 0;
  10911. gestaltStereoMixing      = 1;
  10912.  
  10913. The response gestaltStereoCapability indicates that the Sound Manager can play
  10914. stereo sounds. The response gestaltStereoMixing indicates that the sound
  10915. hardware of the machine mixes both left and right channels of stereo sound into
  10916. a single audio signal for the internal speaker.
  10917.  
  10918. gestaltTextEditVersion
  10919.  
  10920. Returns a value that indicates which version of TextEdit is present.
  10921.  
  10922. CONST
  10923. gestaltTE1  = 1;
  10924. gestaltTE2  = 2;
  10925. gestaltTE3  = 3;
  10926. gestaltTE4  = 4;
  10927.   
  10928. See the TextEdit chapter in this volume for further information on the
  10929. capabilities of these enhanced versions of TextEdit.
  10930.  
  10931. gestaltTimeMgrVersion
  10932.  
  10933. Returns a value that indicates the version of the Time Manager that is present.
  10934.  
  10935. CONST
  10936. gestaltStandardTimeMgr  = 1;
  10937. gestaltRevisedTimeMgr   = 2;
  10938. gestaltExtendedTimeMgr  = 3;
  10939.  
  10940. See the Time Manager chapter in this volume for a complete explanation of the
  10941. capabilities of each of these three versions.
  10942.  
  10943. gestaltVMAttr
  10944.  
  10945. Returns information about virtual memory.
  10946.  
  10947. CONST
  10948. gestaltVMPresent  = 1;
  10949. _______________________________________________________________________________
  10950.  
  10951. æKY Interpreting…Responses…to…Informational…Selectors
  10952. æC »Interpreting Responses to Informational Selectors             Compatibility Guidelines
  10953. _______________________________________________________________________________
  10954.  
  10955. Gestalt returns the following responses when passed a predefined informational
  10956. selector.
  10957.  
  10958. † Warning:  Never infer the existence of certain hardware or software features
  10959. from the responses that Gestalt returns to your application when you pass it
  10960. these selectors.Ê
  10961.  
  10962. gestaltMachineType
  10963.  
  10964. Returns one of the following values, indicating the type of machine on which the
  10965. application is currently running.
  10966.  
  10967. CONST
  10968. gestaltClassic   = 1;  {Macintosh 128K}
  10969. gestaltMacXL     = 2;  {Macintosh XL}
  10970. gestaltMac512KE  = 3;  {Macintosh 512KE }
  10971. gestaltMacPlus   = 4;  {Macintosh Plus}
  10972. gestaltMacSE     = 5;  {Macintosh SE}
  10973. gestaltMacII     = 6;  {Macintosh II}
  10974. gestaltMacIIx    = 7;  {Macintosh IIx}
  10975. gestaltMacIIcx   = 8;  {Macintosh IIcx}
  10976. gestaltMacSE030  = 9;  {Macintosh SE/30}
  10977. gestaltPortable  = 10; {Macintosh Portable}
  10978. gestaltMacIIci   = 11; {Macintosh IIci}
  10979.   
  10980. Note that the machine type does not indicate which version or size of ROM is
  10981. installed. To determine that information, you should use the two selectors
  10982. gestaltROMSize and gestaltROMVersion.
  10983.  
  10984. gestaltROMSize
  10985.  
  10986. Returns the size of the installed ROM. The value is returned in a word.
  10987.  
  10988. gestaltROMVersion
  10989.  
  10990. Returns the version number of the installed ROM.
  10991.  
  10992. gestaltSystemVersion
  10993.  
  10994. Returns the version number of the currently active System file. This number is
  10995. represented as two byte-long numbers. For example, if your application is
  10996. running in version 6.0.4, then Gestalt returns the value $0604. You should
  10997. ignore the high-order word of the returned value.
  10998.  
  10999. _______________________________________________________________________________
  11000.  
  11001. æKY Adding…Gestalt…Selectors
  11002. æC »Adding Gestalt Selectors                                      Compatibility Guidelines
  11003. _______________________________________________________________________________
  11004.  
  11005. You can add a new selector code to those already understood by Gestalt by
  11006. calling the NewGestalt function. The NewGestalt function requires two
  11007. parameters. The first parameter is the new selector to be registered. The second
  11008. parameter is the address of a selector function, a function that is to be
  11009. executed by Gestalt when it needs to determine what value to pass back when it
  11010. is called with the new selector code.
  11011.  
  11012. The selector code is a four-character sequence of type OSType. For example, 
  11013. Carl’s Object-Oriented Linker might register itself using the selector code 
  11014. 'COOL'. If you have registered a creator string with Apple, you are strongly
  11015. encouraged to use that sequence as your selector code.
  11016.  
  11017. Note:  Apple reserves for its own use all four-character sequences consisting
  11018. solely of lowercase letters and nonalphabetic ASCII characters.
  11019.  
  11020. The selector function whose address you specify when registering a new Gestalt
  11021. selector code can be any function that resides in the system heap and whose
  11022. calling syntax conforms to that defined in “Specifying Gestalt Selector
  11023. Functions” later in this chapter. Listing 3-6 illustrates how to install a
  11024. simple function into the system heap and pass its address to NewGestalt.
  11025.  
  11026. Listing 3-6.  Installing a selector function into the system heap
  11027.  
  11028. PROGRAM NewGestaltSample;
  11029. USES
  11030.   Memtypes, OSIntf, ToolIntf,   {standard includes}
  11031.   PasLibIntf,        {for standard I/O, etc.}
  11032.   GestaltEqu,       {for Gestalt}
  11033.   Traps;        {for trap numbers}
  11034. CONST
  11035.   mySelector    = 'COOL';  {Gestalt function selector}
  11036.   gstFuncRsrcType  = 'GDEF';  {Gestalt function resource type}
  11037.   gstFuncRsrcID  = 128;  {Gestalt function resource ID}
  11038. VAR
  11039.   gestaltErr:    OSErr;  {error returned by Gestalt}
  11040.   gstFuncHandle:  Handle;  {handle to Gestalt function}
  11041.   oldGestaltFunc:  ProcPtr;  {pointer to old function}
  11042. BEGIN
  11043.   {first make sure that Gestalt is available}
  11044.   IF NOT TrapAvailable(_Gestalt) THEN
  11045.     BEGIN
  11046.       WriteLn('Gestalt is not implemented.');
  11047.       IEexit(1)
  11048.     END;
  11049.   {load Gestalt function resource into system heap}
  11050.   gstFuncHandle := GetResource(gstFuncRsrcType, gstFuncRsrcID);
  11051.   IF gstFuncHandle = NIL THEN
  11052.     BEGIN
  11053.       WriteLn('Could not load Gestalt function resource.');
  11054.       IEexit(1)
  11055.     END;
  11056.   {detach it from the resource map so it stays around}
  11057.   DetachResource(gstFuncHandle);
  11058.   {add the new selector; first assume that it doesn't already exist}
  11059.   gestaltErr := NewGestalt(mySelector, ProcPtr(gstFuncHandle^));
  11060.   IF gestaltErr <> noErr THEN
  11061.     BEGIN
  11062.       WriteLn('Could not add as a new selector.');
  11063.       {try to replace existing selector}
  11064.       gestaltErr := ReplaceGestalt(mySelector,
  11065.         ProcPtr(gstFuncHandle^), oldGestaltFunc);
  11066.       IF gestaltErr <> noErr THEN
  11067.       BEGIN
  11068.         WriteLn('Could not replace selector either.');
  11069.         IEexit(1);
  11070.       END
  11071.     END;
  11072.   WriteLn('Selector installed.');
  11073. END.
  11074.  
  11075. You can ensure that the new Gestalt selector function is installed into the
  11076. system heap by defining it as a resource (in this case, of type 'GDEF') whose
  11077. resource attributes are resSysHeap and resLocked (in other words, lock the
  11078. resource into the system heap). Listing 3-7 shows the relevant lines from a
  11079. Makefile.
  11080.  
  11081. Listing 3-7.  Makefile directives to create a 'GDEF' resource
  11082.  
  11083. GestaltFunc.p.o      ƒ  GestaltFunc.p
  11084.   Pascal GestaltFunc.p
  11085.  
  11086. NewGestaltSample    ƒƒ  GestaltFunc.p.o
  11087.   Link GestaltFunc.p.o -rn ∂
  11088.            -ra =resSysHeap,resLocked ∂
  11089.            -rt GDEF=128
  11090.            -o NewGestaltSample
  11091.  
  11092. Listing 3-8 shows the actual function definition, contained in the file
  11093. GestaltFunc.p.
  11094.  
  11095. Listing 3-8.  Defining a new Gestalt function
  11096.  
  11097. UNIT GestaltFunc;
  11098. INTERFACE
  11099.   USES
  11100.     GestaltEqu;      {for Gestalt}
  11101.   CONST
  11102.     myResult  = $87654321;  {Gestalt function response}
  11103.   FUNCTION gestaltCool (gestaltSelector: OSType;
  11104.             VAR gestaltResponse: LongInt) : OSErr;
  11105.  
  11106. IMPLEMENTATION
  11107.   FUNCTION gestaltCool;
  11108.     BEGIN
  11109.       gestaltResponse := myResult;  {return our response}
  11110.       gestaltCool := noErr;    {return no error}
  11111.     END;
  11112. END.
  11113.  
  11114. Because the new selector function resides in the system heap, Gestalt recognizes
  11115. and responds to the new selector until the machines restarts, even if your
  11116. application terminates before that time. As a result, you might want your
  11117. selector function to determine whether your application is still running before
  11118. returning a value to Gestalt. If your application has terminated, the selector
  11119. function should return an error.
  11120.  
  11121. Note that if you try to register a selector that has already been registered
  11122. with Gestalt, an error results.
  11123.  
  11124. _______________________________________________________________________________
  11125.  
  11126. æKY Modifying…Gestalt…Selectors
  11127. æC »Modifying Gestalt Selectors                                   Compatibility Guidelines
  11128. _______________________________________________________________________________
  11129.  
  11130. You can use the ReplaceGestalt function to modify the function that Gestalt
  11131. executes when passed a particular selector code. As with the function whose
  11132. address is passed to NewGestalt, the new function must must reside in the system
  11133. heap and have a calling syntax that conforms to that defined in “Specifying
  11134. Gestalt Selector Functions” later in this chapter. Listing 3-6 illustrates how
  11135. to replace a Gestalt selector function.
  11136.  
  11137. To allow the new function to call the function previously associated with the
  11138. selector in question, the ReplaceGestalt function returns the address of the
  11139. previous function.
  11140.  
  11141. If you attempt to redefine a selector that is not yet defined, an error is
  11142. returned; in that case, the address of the previous function is undefined.
  11143. Accordingly, you should always test the result code of ReplaceGestalt before
  11144. calling Gestalt with the selector in question.
  11145.  
  11146. Note:  If you modify the function associated with a predefined Gestalt selector,
  11147. do not use any bits in the response parameter that are not documented in this
  11148. chapter. Apple reserves all undocumented bits in the response parameter returned
  11149. by predefined Gestalt selectors.  
  11150. _______________________________________________________________________________
  11151.  
  11152. æKY Specifying…Gestalt…Selector…Functions
  11153. æC »Specifying Gestalt Selector Functions                         Compatibility Guidelines
  11154. _______________________________________________________________________________
  11155.  
  11156. When you call the NewGestalt and ReplaceGestalt functions, you need to supply
  11157. the address of a selector function that is called when some application passes
  11158. the specified new or replacement selector to Gestalt. This selector function
  11159. should have the following syntax and must reside in the system heap.
  11160.  
  11161. FUNCTION selectorFunction (selector: OSType; VAR response: LongInt) : OSErr;
  11162.  
  11163. When you pass the new or replacement selector to Gestalt, Gestalt calls the
  11164. specified selector function to determine the information that Gestalt should
  11165. pass back to the calling software. Your function should place the result in the
  11166. long integer pointed to by the response parameter and should return the result
  11167. code that Gestalt will return. This function should be as simple as possible and
  11168. cannot use global variables in the A5 world unless A5 is set up explicitly and
  11169. then restored upon exit. (See the Memory Management chapter in this volume for
  11170. an explanation of setting up and restoring the A5 world.) Other Gestalt
  11171. functions may be called using Gestalt from within this function.
  11172.  
  11173. _______________________________________________________________________________
  11174.  
  11175. æKY Gestalt…Manager…Routines
  11176. æC »GESTALT MANAGER ROUTINES                                      Compatibility Guidelines
  11177. _______________________________________________________________________________
  11178.  
  11179. This section describes the three functions in the Gestalt Manager—Gestalt,
  11180. NewGestalt, and ReplaceGestalt. They allow you, respectively, to determine what
  11181. hardware and software features are present in the operating environment, to add
  11182. new selectors to those understood by the Gestalt function, and to replace the
  11183. functions associated with known selectors.
  11184.  
  11185. _______________________________________________________________________________
  11186.  
  11187. æKY Getting…Information…About…the…Operating…Environment
  11188. æC »Getting Information About the Operating Environment           Compatibility Guidelines
  11189. _______________________________________________________________________________
  11190.  
  11191. Use the Gestalt function to obtain information about the operating environment.
  11192. The information you need is indicated by the selector parameter, which Gestalt
  11193. must already recognize.
  11194.  
  11195. FUNCTION Gestalt (selector: OSType; VAR response: LongInt) : OSErr;
  11196.  
  11197. Trap macro  _Gestalt
  11198. On entry    D0: selector code
  11199. On exit     A0: response
  11200.             D0: result code
  11201.  
  11202. Upon successful completion of the function, the response parameter contains the
  11203. information requested. Note that Gestalt returns the results from all function
  11204. selectors in a long integer, occupying 4 bytes. In some cases, not all 4 bytes
  11205. are needed to hold the returned information, in which case Gestalt places the
  11206. information in the low-order bytes of the response parameter.
  11207.  
  11208. Result codes
  11209. noErr                        0  No error
  11210. gestaltUnknownErr        –5550  Could not obtain the response
  11211. gestaltUndefSelectorErr  –5551  Undefined selector
  11212. _______________________________________________________________________________
  11213.  
  11214. æKY Adding…Selector…Codes
  11215. æC »Adding Selector Codes                                         Compatibility Guidelines
  11216. _______________________________________________________________________________
  11217.  
  11218. Use the NewGestalt function to add selector codes to those already recognized by
  11219. Gestalt.
  11220.  
  11221. FUNCTION NewGestalt (selector: OSType; selectorFunction: ProcPtr) : OSErr;
  11222.  
  11223. Trap macro  _NewGestalt
  11224. On entry    A0: address of new selector function
  11225.             D0: selector code
  11226. On exit     D0: result code
  11227.  
  11228. NewGestalt takes as parameters the selector to be registered and the function
  11229. that Gestalt calls when it receives this selector. The interface for the
  11230. selectorFunction function is defined in “Specifying Gestalt Selector Functions”
  11231. earlier in this chapter.
  11232.  
  11233. Result codes
  11234. noErr                      0  No error
  11235. memFullErr              –108  Ran out of memory
  11236. gestaltDupSelectorErr  –5552  Selector already exists
  11237. gestaltLocationErr     –5553  Function not in system heap
  11238. _______________________________________________________________________________
  11239.  
  11240. æKY Modifying…Selector…Codes
  11241. æC »Modifying Selector Codes                                      Compatibility Guidelines
  11242. _______________________________________________________________________________
  11243.  
  11244. The ReplaceGestalt function allows an application to replace the function that
  11245. is currently associated with a selector.
  11246.  
  11247. FUNCTION ReplaceGestalt (selector: OSType; selectorFunction: ProcPtr;
  11248.             VAR oldGestaltFunction: ProcPtr) : OSErr;
  11249.  
  11250. Trap macro  _ReplaceGestalt
  11251. On entry    A0: address of new selector function
  11252.             D0: selector code
  11253. On exit     A0: address of old selector function
  11254.             D0: result code
  11255.  
  11256. The interface for the selectorFunction function is defined in “Specifying
  11257. Gestalt Selector Functions” earlier in this chapter. The new function must
  11258. reside in the system heap and may want to call the function previously
  11259. associated with the named selector. It may do so by using the address returned
  11260. in the parameter oldGestaltFunction. If ReplaceGestalt returns an error of any
  11261. type, then the value of oldGestaltFunction is undefined.
  11262.  
  11263. Result codes
  11264. noErr                        0  No error
  11265. gestaltUndefSelectorErr  –5551  Undefined selector
  11266. gestaltLocationErr       –5553  Function not in system heap
  11267.  
  11268. _______________________________________________________________________________
  11269.  
  11270. æKY Summary…of…the…Gestalt…Manager
  11271. æC »SUMMARY OF THE GESTALT MANAGER                                Compatibility Guidelines
  11272. _______________________________________________________________________________
  11273.  
  11274. The following cards summarize the constants, data types, and routines for the
  11275. Gestalt Manager.
  11276. _______________________________________________________________________________
  11277.  
  11278. æKY  Gestalt…Manager…Constants
  11279. æC »Constants                                                     Compatibility Guidelines
  11280. _______________________________________________________________________________
  11281.  
  11282. CONST  {environmental selector codes}
  11283. gestaltVersion                 = 'vers';  {Gestalt version}
  11284. gestaltAddressingModeAttr      = 'addr';  {addressing mode attributes}
  11285. gestaltAliasMgrAttr            = 'alis';  {Alias Mgr attributes}
  11286. gestaltAppleTalkVersion        = 'atlk';  {AppleTalk version}
  11287. gestaltAUXVersion              = 'a/ux';  {A/UX version if present}
  11288. gestaltCTBVersion              = 'ctbv';  {Comm Toolbox version}
  11289. gestaltDBAccessMgrAttr         = 'dbac';  {Database Access Mgr attrs}
  11290. gestaltEditionMgrAttr          = 'edtn';  {Edition Mgr attributes}
  11291. gestaltAppleEventsAttr         = 'evnt';  {AppleEvents attributes}
  11292. gestaltFolderMgrAttr           = 'fold';  {Folder Mgr attributes}
  11293. gestaltFontMgrAttr             = 'font';  {Font Mgr attributes}
  11294. gestaltFPUType                 = 'fpu ';  {FPU type}
  11295. gestaltHardwareAttr            = 'hdwr';  {hardware attributes}
  11296. gestaltHelpMgrAttr             = 'help';  {Help Mgr attributes}
  11297. gestaltKeyboardType            = 'kbd ';  {keyboard type}
  11298. gestaltLowMemorySize           = 'lmem';  {low-memory area size}
  11299. gestaltLogicalRAMSize          = 'lram';  {logical RAM size}
  11300. gestaltMiscAttr                = 'misc';  {miscellaneous attributes}
  11301. gestaltMMUType                 = 'mmu ';  {MMU type}
  11302. gestaltNotificationMgrAttr     = 'nmgr';  {Notification Mgr attrs}
  11303. gestaltOSAttr                  = 'os  ';  {O/S attributes}
  11304. gestaltLogicalPageSize         = 'pgsz';  {logical page size}
  11305. gestaltPPCToolboxAttr          = 'ppc ';  {PPC Toolbox attributes}
  11306. gestaltPowerMgrAttr            = 'powr';  {Power Mgr attributes}
  11307. gestaltProcessorType           = 'proc';  {processor type}
  11308. gestaltParityAttr              = 'prty';  {parity attributes}
  11309. gestaltQuickdrawVersion        = 'qd  ';  {QuickDraw version}
  11310. gestaltPhysicalRAMSize         = 'ram ';  {physical RAM size}
  11311. gestaltResourceMgrAttr         = 'rsrc';  {Resource Mgr attributes}
  11312. gestaltScriptMgrVersion        = 'scri';  {Script Mgr version}
  11313. gestaltScriptCount             = 'scr#';  {# of active script systems}
  11314. gestaltSoundAttr               = 'snd ';  {sound attributes}
  11315. gestaltTextEditVersion         = 'te  ';  {TextEdit version}
  11316. gestaltTimeMgrVersion          = 'tmgr';  {Time Mgr version}
  11317. gestaltVMAttr                  = 'vm  ';  {virtual memory attributes}
  11318.   
  11319. {informational selector codes}
  11320. gestaltMachineType             = 'mach';  {machine type}
  11321. gestaltROMSize                 = 'rom ';  {ROM size}
  11322. gestaltROMVersion              = 'romv';  {ROM version}
  11323. gestaltSystemVersion           = 'sysv';  {System file version}
  11324.   
  11325. {gestaltAddressingModeAttr response values}
  11326. gestalt32BitAddressing         = 0;  {true if booted in 32-bit mode}
  11327. gestalt32BitSysZone            = 1;  {32-bit compatible system zone}
  11328. gestalt32BitCapable            = 2;  {machine is 32-bit capable}
  11329.   
  11330. {gestaltAliasMgrAttr response values}
  11331. gestaltAliasMgrPresent         = 0;  {true if Alias Mgr is present}
  11332.   
  11333. {gestaltDBAccessMgrAttr response values}
  11334. gestaltDBAccessMgrPresent      = 0;  {true if DB Access Mgr present}
  11335.   
  11336. {gestaltEditionMgrAttr response values}
  11337. gestaltEditionMgrPresent       = 0;  {true if Edition Mgr present}
  11338.   
  11339. {gestaltAppleEventsAttr response values}
  11340. gestaltAppleEventsPresent      = 0;  {true if AppleEvents present}
  11341.   
  11342. {gestaltFolderMgrAttr response values}
  11343. gestaltFolderMgrPresent        = 0;  {true if Folder Mgr present}
  11344.   
  11345. {gestaltFontMgrAttr response values}
  11346. gestaltOutlineFonts            = 0;  {true if outline fonts present}
  11347.   
  11348. {gestaltFPUType response values}
  11349. gestaltNoFPU                   = 0;  {no FPU present}
  11350. gestalt68881                   = 1;  {Motorola 68881 present}
  11351. gestalt68882                   = 2;  {Motorola 68882 present}
  11352.   
  11353. {gestaltHardwareAttr response values}
  11354. gestaltHasVIA1                 = 0;  {has a VIA1}
  11355. gestaltHasVIA2                 = 1;  {has a VIA2}
  11356. gestaltHasASC                  = 3;  {has an ASC}
  11357. gestaltHasSCC                  = 4;  {has an SCC}
  11358. gestaltHasSCSI                 = 7;  {has SCSI}
  11359.    
  11360. {gestaltHelpMgrAttr response values}
  11361. gestaltHelpMgrPresent          = 0;  {true if Help Mgr present}
  11362.   
  11363. {gestaltKeyboardType response values}
  11364. gestaltMacKbd                  = 1;  {Mac keyboard}
  11365. gestaltMacAndPad               = 2;  {Mac keyboard and keypad}
  11366. gestaltMacPlusKbd              = 3;  {Mac Plus keyboard}
  11367. gestaltExtADBKbd               = 4;  {Extended ADB keyboard}
  11368. gestaltStdADBKbd               = 5;  {Standard ADB keyboard}
  11369. gestaltPrtblADBKbd             = 6;  {Portable Std ADB keyboard}
  11370. gestaltPrtblISOKbd             = 7;  {Portable ISO ADB keyboard}
  11371. gestaltStdISOADBKbd            = 8;  {ISO Std ADB keyboard}
  11372. gestaltExtISOADBKbd            = 9;  {ISO Ext ADB keyboard}
  11373.   
  11374. {gestaltMiscAttr response values}
  11375. gestaltScrollingThrottle       = 0;  {true if scrolling throttle on}
  11376.   
  11377. {gestaltMMUType response values}
  11378. gestaltNoMMU                   = 0;  {no MMU present}
  11379. gestaltAMU                     = 1;  {Mac II addr management unit}
  11380. gestalt68851                   = 2;  {Motorola 68851 PMMU}
  11381. gestalt68030MMU                = 3;  {Motorola 68030 built-in MMU}
  11382.   
  11383. {gestaltNotificationMgrAttr response values}
  11384. gestaltNotificationMgrPresent  = 0;  {Notification Mgr present}
  11385.   
  11386. {gestaltOSAttr response values}
  11387. gestaltSysZoneGrowable         = 0;  {system heap can grow}
  11388. gestaltLaunchCanReturn         = 1;  {can return from launch}
  11389. gestaltLaunchFullFileSpec      = 2;  {can launch from full filespec}
  11390. gestaltLaunchControl           = 3;  {launch control support}
  11391. gestaltTempMemSupport          = 4;  {temp memory support present}
  11392. gestaltRealTempMemory          = 5;  {temp memory handles are real}
  11393. gestaltTempMemTracked          = 6;  {temp memory handles tracked}
  11394. gestaltIPCSupport              = 7;  {IPC support is present}
  11395. gestaltSysDebuggerSupport      = 8;  {system debugger support}
  11396.   
  11397. gestaltPowerMgrAttr response values}
  11398. gestaltPMgrExists              = 0;  {Power Manager is present}
  11399. gestaltPMgrCPUIdle             = 1;  {CPU can idle}
  11400. gestaltPMgrSCC                 = 2;  {can stop SCC clock}
  11401. gestaltPMgrSound               = 3;  {can turn off sound power}
  11402.   
  11403. {gestaltPPCToolboxAttr response values}
  11404. gestaltPPCToolboxPresent       = 0;  {PPC Toolbox is present}
  11405. gestaltPPCRealTime             = 1;  {real-time delivery}
  11406.  
  11407. {gestaltProcessorType response values}
  11408. gestalt68000                   = 1;
  11409. gestalt68010                   = 2;
  11410. gestalt68020                   = 3;
  11411. gestalt68030                   = 4;
  11412.  
  11413. {gestaltParityAttr response values}
  11414. gestaltHasParityCapability     = 0;  {machine can check parity}
  11415. gestaltParityEnabled           = 1;  {parity RAM is installed} 
  11416.   
  11417. {gestaltQuickdrawVersion response values}
  11418. gestaltOriginalQD              = $000;  {original QuickDraw}
  11419. gestalt8BitQD                  = $100;  {8-bit Color QuickDraw}
  11420. gestalt32BitQD                 = $200;  {32-Bit Color QuickDraw}
  11421.   
  11422. {gestaltResourceMgrAttr response values}
  11423. gestaltPartialRsrcsExist       = 0;  {partial resource functions exist}
  11424. gestaltDecompression           = 1;  {}
  11425.   
  11426. {gestaltSoundAttr response values}
  11427. gestaltStereoCapability        = 0;  {stereo capability present}
  11428. gestaltStereoMixing            = 1;  {stereo mixing on internal speaker}
  11429.   
  11430. {gestaltTextEditVersion response values}
  11431. gestaltTE1                     = 1;  {in MacIIci ROM}
  11432. gestaltTE2                     = 2;  {with 6.0.4 scripts on Mac IIci}
  11433. gestaltTE3                     = 3;  {with 6.0.4 scripts on other machines}
  11434. gestaltTE4                     = 4;  {in 6.0.5 and 7.0}
  11435.   
  11436. {gestaltTimeMgrVersion response values}
  11437. gestaltStandardTimeMgr  = 1;  {standard Time Manager}
  11438. gestaltRevisedTimeMgr   = 2;  {revised Time Manager}
  11439. gestaltExtendedTimeMgr  = 3;  {extended Time Manager}
  11440.   
  11441. {gestaltVMAttr response values}
  11442. gestaltVMPresent  = 1;  {virtual memory present}
  11443.   
  11444. gestaltMachineType response values}
  11445. gestaltClassic   = 1;  {Macintosh 128K}
  11446. gestaltMacXL     = 2;  {Macintosh XL}
  11447. gestaltMac512KE  = 3;  {Macintosh 512K Enhanced}
  11448. gestaltMacPlus   = 4;  {Macintosh Plus}
  11449. gestaltMacSE     = 5;  {Macintosh SE}
  11450. gestaltMacII     = 6;  {Macintosh II}
  11451. gestaltMacIIx    = 7;  {Macintosh IIx}
  11452. gestaltMacIIcx   = 8;  {Macintosh IIcx}
  11453. gestaltMacSE030  = 9;  {Macintosh SE/30}
  11454. gestaltPortable  = 10; {Macintosh Portable}
  11455. gestaltMacIIci   = 11; {Macintosh IIci}
  11456. _______________________________________________________________________________
  11457.  
  11458. æKY Gestalt…Manager…Routines…Summary
  11459. æC »Routines                                                      Compatibility Guidelines
  11460. _______________________________________________________________________________
  11461.  
  11462. FUNCTION Gestalt  (selector: OSType; VAR response: LongInt) : OSErr;
  11463.  
  11464. FUNCTION NewGestalt  (selector: OSType; selectorFunction: ProcPtr) : OSErr;
  11465.  
  11466. FUNCTION ReplaceGestalt  (selector: OSType; selectorFunction: ProcPtr; VAR 
  11467.                           oldGestaltFunction: ProcPtr) : OSErr;
  11468. _______________________________________________________________________________
  11469.  
  11470. æKY Gestalt…Manager…Result…Codes
  11471. æC »Result Codes                                                  Compatibility Guidelines
  11472. _______________________________________________________________________________
  11473.  
  11474. noErr                        0  No error
  11475. memFullErr                –108  Ran out of memory
  11476. gestaltUnknownErr        –5550  Could not obtain the response
  11477. gestaltUndefSelectorErr  –5551  Undefined selector
  11478. gestaltDupSelectorErr    –5552  Selector already exists
  11479. gestaltLocationErr       –5553  Function not in system heap
  11480. _______________________________________________________________________________
  11481.  
  11482.  
  11483. æKY ControlManager
  11484. æC 
  11485. THE CONTROL MANAGER                                           
  11486. _______________________________________________________________________________
  11487.  
  11488. About…The…ControlManager…Chapter
  11489. About…the…Control…Manager
  11490. Controls…and…Windows
  11491. Controls…and…Resources
  11492. Part…Codes
  11493. Control…Records
  11494. Auxiliary…Control…Records
  11495. Control…Color…Tables
  11496. The…Control…Color…Table…Resource
  11497. Using…the…Control…Manager
  11498. Using…Color…Controls
  11499. Control…Manager…Routines
  11500. Defining…Your…Own…Controls
  11501. Formats…of…Resources…for…Controls
  11502. Summary…of…the…Control…Manager
  11503. _______________________________________________________________________________
  11504.  
  11505.  
  11506.  
  11507. æKY About…The…ControlManager…Chapter
  11508. æC »ABOUT THIS CHAPTER                                        ControlManager
  11509. _______________________________________________________________________________
  11510.  
  11511. This chapter describes the Control Manager, the part of the Toolbox that deals with
  11512. controls, such as buttons, check boxes, and scroll bars. Using the Control Manager,
  11513. your application can create, manipulate, and dispose of controls.
  11514.  
  11515. You should already be familiar with:
  11516.  
  11517.   •  resources, as discussed in the Resource Manager chapter
  11518.   •  the basic concepts and structures behind QuickDraw, particularly points,
  11519.      rectangles, regions, and grafPorts
  11520.   •  the Toolbox Event Manager
  11521.   •  the Window Manager
  11522.  
  11523. This chapter also describes the enhancements to the Control Manager provided for the
  11524. Macintosh Plus, Macintosh SE, and Macintosh II. A new set of Control Manager routines
  11525. now supports the use of color controls. All handling of color controls is transparent
  11526. to applications that aren’t using the new features.
  11527.  
  11528. The structure and size of a control record are unchanged. A new data structure, the
  11529. auxiliary control record, has been introduced to carry additional color information
  11530. for a control, and a new system resource, 'cctb', stores control color table information.
  11531. Three new routines have been added to support the use of color.
  11532.  
  11533. _______________________________________________________________________________
  11534.  
  11535.  
  11536. æKY About…the…Control…Manager
  11537. æC »ABOUT THE CONTROL MANAGER                                  ControlManager
  11538. _______________________________________________________________________________
  11539.  
  11540. The Control Manager is the part of the Toolbox that deals with controls. A control is
  11541. an object on the Macintosh screen with which the user, using the mouse, can cause
  11542. instant action with visible results or change settings to modify a future action.
  11543. Using the Control Manager, your application can:
  11544.  
  11545.   •  create and dispose of controls
  11546.   •  display or hide controls
  11547.   •  monitor the user’s operation of a control with the mouse and
  11548.      respond accordingly
  11549.   •  read or change the setting or other properties of a control
  11550.   •  change the size, location, or appearance of a control
  11551.  
  11552. Your application performs these actions by calling the appropriate Control Manager
  11553. routines. The Control Manager carries out the actual operations, but
  11554. it’s up to you to decide when, where, and how.
  11555.  
  11556. Controls may be of various types (see Figure 1), each with its own characteristic
  11557. appearance on the screen and responses to the mouse. Each individual control has its
  11558. own specific properties— such as its location, size, and setting—but controls of the
  11559. same type behave in the same general way.
  11560.  
  11561. Certain standard types of controls are predefined for you. Your application can
  11562. easily create and use controls of these standard types, and can also define its own
  11563. “custom” control types. Among the standard control types are the following:
  11564.  
  11565.   •  Buttons cause an immediate or continuous action when clicked or pressed
  11566.      with the mouse. They appear on the screen as rounded-corner rectangles
  11567.      with a title centered inside.
  11568.  
  11569.   •  Check boxes retain and display a setting, either checked (on) or
  11570.      unchecked (off); clicking with the mouse reverses the setting. On the
  11571.      screen, a check box appears as a small square with a title alongside it;
  11572.      the box is either filled in with an “X” (checked) or empty (unchecked).
  11573.      Check boxes are frequently used to control or modify some future action,
  11574.      instead of causing an immediate action of their own.
  11575.  
  11576.   •  Radio buttons also retain and display an on-or-off setting. They’re
  11577.      organized into groups, with the property that only one button in the
  11578.      group can be on at a time:  Clicking one button in a group both turns it
  11579.      on and turns off the button that was on, like the buttons on a car radio.
  11580.      Radio buttons are used to offer a choice among several alternatives. On
  11581.      the screen, they look like round check boxes; the radio button that’s on
  11582.      is filled in with a small black circle instead of an “X”.
  11583.  
  11584. •••Refer to Figure 1.•••
  11585.  
  11586. Figure 1–Controls
  11587.  
  11588. Note:  The Control Manager doesn’t know how radio buttons are grouped,
  11589.        and doesn’t automatically turn one off when the user clicks another
  11590.        one on:  It’s up to your program to handle this
  11591.  
  11592. Another important category of controls is dials. These display the value, magnitude,
  11593. or position of something, typically in some pseudo-analog form such as the position
  11594. of a sliding switch, the reading on a thermometer scale, or the angle of a needle on
  11595. a gauge; the setting may be displayed digitally as well. The control’s moving part
  11596. that displays the current setting is called the indicator. The user may be able to
  11597. change a dial’s setting by dragging its indicator with the mouse, or the dial may
  11598. simply display a value not under the user’s direct control (such as the amount of
  11599. free space remaining on a disk).
  11600.  
  11601. One type of dial is predefined for you:  The standard Macintosh scroll bars. Figure 2
  11602. shows the five parts of a scroll bar and the terms used by the Control Manager (and
  11603. this chapter) to refer to them. Notice that the part of the scroll bar that Macintosh
  11604. users know as the “scroll box” is called the “thumb” here. Also, for simplicity, the
  11605. terms “up” and “down” are used even when referring to horizontal scroll bars (in
  11606. which case “up” really means “left” and “down” means “right”).
  11607.  
  11608. •••Refer to Figure 2.•••
  11609.  
  11610. Figure 2–Parts of a Scroll Bar
  11611.  
  11612. The up and down arrows scroll the window’s contents a line at a time. The two paging
  11613. regions scroll a “page” (windowful) at a time. The thumb can be dragged to any position
  11614. in the scroll bar, to scroll to a corresponding position within the document. Although
  11615. they may seem to behave like individual controls, these are all parts of a single
  11616. control, the scroll bar type of dial. You can define other dials of any shape or
  11617. complexity for yourself if your application needs them.
  11618.  
  11619. A control may be active or inactive. Active controls respond to the user’s mouse
  11620. actions; inactive controls don’t. When an active control is clicked or pressed, it’s
  11621. usually highlighted (see Figure 3). Standard button controls are inverted, but some
  11622. control types may use other forms of highlighting, such as making the outline heavier.
  11623. It’s also possible for just a part of a control to be highlighted:  For example, when
  11624. the user presses the mouse button inside a scroll arrow or the thumb in a scroll bar,
  11625. the arrow or thumb (not the whole scroll bar) becomes highlighted until the button is
  11626. released.
  11627.  
  11628. •••Refer to Figure 3.•••
  11629.  
  11630. Figure 3–Highlighted Active Controls
  11631.  
  11632. A control is made inactive when it has no meaning or effect in the current context,
  11633. such as an “Open” button when no document has been selected to open, or a scroll bar
  11634. when there’s currently nothing to scroll to. An inactive control remains visible, but
  11635. is highlighted in some special way, depending on its control type (see Figure 4). For
  11636. example, the title of an inactive button, check box, or radio button is dimmed (drawn
  11637. in gray rather than black).
  11638.  
  11639. •••Refer to Figure 4.•••
  11640.  
  11641. Figure 4–Inactive Controls
  11642.  
  11643. _______________________________________________________________________________
  11644.  
  11645.  
  11646. æKY Controls…and…Windows
  11647. æC »CONTROLS AND WINDOWS                                       ControlManager
  11648. _______________________________________________________________________________
  11649.  
  11650. Every control “belongs” to a particular window:  When displayed, the control appears
  11651. within that window’s content region; when manipulated with the mouse, it acts on that
  11652. window. All coordinates pertaining to the control (such as those describing its
  11653. location) are given in its window’s local coordinate system.
  11654.  
  11655. Warning:  In order for the Control Manager to draw a control properly, the
  11656.           control’s window must have the top left corner of its grafPort’s
  11657.           portRect at coordinates (0,0). If you change a window’s local
  11658.           coordinate system for any reason (with the QuickDraw procedure
  11659.           SetOrigin), be sure to change it back—so that the top left corner
  11660.           is again at (0,0)—before drawing any of its controls. Since almost
  11661.           all of the Control Manager routines can (at least potentially)
  11662.           redraw a control, the safest policy is simply to change the
  11663.           coordinate system back before calling any Control Manager routine.
  11664.  
  11665. Normally you’ll include buttons and check boxes in dialog or alert windows only. You
  11666. create such windows with the Dialog Manager, and the Dialog Manager takes care of
  11667. drawing the controls and letting you know whether the user clicked one of them. See
  11668. the Dialog Manager chapter for details.
  11669.  
  11670. _______________________________________________________________________________
  11671.  
  11672.  
  11673. æKY Controls…and…Resources
  11674. æC »CONTROLS AND RESOURCES                                     ControlManager
  11675. _______________________________________________________________________________
  11676.  
  11677. The relationship between controls and resources is analogous to the relationship
  11678. between windows and resources:  Just as there are window definition functions and
  11679. window templates, there are control definition functions and control templates.
  11680.  
  11681. Each type of control has a control definition function that determines how controls
  11682. of that type look and behave. The Control Manager calls the control definition function
  11683. whenever it needs to perform a type-dependent action, such as drawing the control on
  11684. the screen. Control definition functions are stored as resources and accessed through
  11685. the Resource Manager. The system resource file includes definition functions for the
  11686. standard control types (buttons, check boxes, radio buttons, and scroll bars). If you
  11687. want to define your own, nonstandard control types, you’ll have to write control
  11688. definition functions for them, as described later in the section “Defining Your Own
  11689. Controls”.
  11690.  
  11691. When you create a control, you specify its type with a control definition ID, which
  11692. tells the Control Manager the resource ID of the definition function for that control
  11693. type. The Control Manager provides the following predefined constants for the definition
  11694. IDs of the standard control types:
  11695.  
  11696. CONST  pushButProc    = 0;    {simple button}
  11697.        checkBoxProc   = 1;    {check box}
  11698.        radioButProc   = 2;    {radio button}
  11699.        scrollBarProc  = 16;   {scroll bar}
  11700.  
  11701. Note:  The control definition function for scroll bars figures out whether
  11702.        a scroll bar is vertical or horizontal from a rectangle you specify
  11703.        when you create the control.
  11704.  
  11705. The title of a button, check box, or radio button normally appears in the system
  11706. font, but you can add the following constant to the definition ID to specify that you
  11707. instead want to use the font currently associated with the window’s grafPort:
  11708.  
  11709. CONST  useWFont       = 8;    {use window's font}
  11710.  
  11711. To create a control, the Control Manager needs to know not only the control definition
  11712. ID but also other information specific to this control, such as its title (if any),
  11713. the window it belongs to, and its location within the window. You can supply all the
  11714. needed information in individual parameters to a Control Manager routine, or you can
  11715. store it in a control template in a resource file and just pass the template’s resource
  11716. ID. Using templates is highly recommended, since it simplifies the process of creating
  11717. controls and isolates the control descriptions from your application’s code.
  11718.  
  11719. _______________________________________________________________________________
  11720.  
  11721.  
  11722. æKY Part…Codes
  11723. æC »PART CODES                                                 ControlManager
  11724. _______________________________________________________________________________
  11725.  
  11726. Some controls, such as buttons, are simple and straightforward. Others can be complex
  11727. objects with many parts:  For example, a scroll bar has two scroll arrows, two paging
  11728. regions, and a thumb (see Figure 2 above). To allow different parts of a control to
  11729. respond to the mouse in different ways, many of the Control Manager routines accept a
  11730. part code as a parameter or return one as a result.
  11731.  
  11732. A part code is an integer between 1 and 253 that stands for a particular part of a
  11733. control. Each type of control has its own set of part codes, assigned by the control
  11734. definition function for that type. A simple control such as a button or check box
  11735. might have just one “part” that encompasses the entire control; a more complex control
  11736. such as a scroll bar can have as many parts as are needed to define how the control
  11737. operates.
  11738.  
  11739. Note:  The values 254 and 255 aren’t used for part codes—254 is reserved
  11740.        for future use, and 255 means the entire control is inactive.
  11741.  
  11742. The part codes for the standard control types are as follows:
  11743.  
  11744. CONST  inButton      = 10;    {simple button}
  11745.        inCheckBox    = 11;    {check box or radio button}
  11746.        inUpButton    = 20;    {up arrow of a scroll bar}
  11747.        inDownButton  = 21;    {down arrow of a scroll bar}
  11748.        inPageUp      = 22;    {"page up" region of a scroll bar}
  11749.        inPageDown    = 23;    {"page down" region of a scroll bar}
  11750.        inThumb       = 129;   {thumb of a scroll bar}
  11751.  
  11752. Notice that inCheckBox applies to both check boxes and radio buttons.
  11753.  
  11754. Note:  For special information about assigning part codes to your own
  11755.        control types, see “Defining Your Own Controls”.
  11756.  
  11757. _______________________________________________________________________________
  11758.  
  11759.  
  11760. æKY Control…Records
  11761. æC »CONTROL RECORDS                                            ControlManager
  11762. _______________________________________________________________________________
  11763.  
  11764. Every control is represented internally by a control record containing all pertinent
  11765. information about that control. The control record contains the following:
  11766.  
  11767.   •  A pointer to the window the control belongs to.
  11768.   •  A handle to the next control in the window’s control list.
  11769.   •  A handle to the control definition function.
  11770.   •  The control’s title, if any.
  11771.   •  A rectangle that completely encloses the control, which determines
  11772.      the control’s size and location within its window. The entire control,
  11773.      including the title of a check box or radio button, is drawn inside
  11774.      this rectangle.
  11775.   •  An indication of whether the control is currently active and how it’s
  11776.      to be highlighted.
  11777.   •  The current setting of the control (if this type of control retains a
  11778.      setting) and the minimum and maximum values the setting can assume. For
  11779.      check boxes and radio buttons, a setting of 0 means the control is off
  11780.      and 1 means it’s on.
  11781.  
  11782. The control record also contains an indication of whether the control is currently
  11783. visible or invisible. These terms refer only to whether the control is drawn in its
  11784. window, not to whether you can see it on the screen. A control may be “visible” and
  11785. still not appear on the screen, because it’s obscured by overlapping windows or other
  11786. objects.
  11787.  
  11788. There’s a field in the control record for a pointer to the control’s default action
  11789. procedure. An action procedure defines some action to be performed repeatedly for as
  11790. long as the user holds down the mouse button inside the control. The default action
  11791. procedure may be used by the Control Manager function TrackControl if you call it
  11792. without passing a pointer to an action procedure; this is discussed in detail in the
  11793. description of TrackControl in the “Control Manager Routines” section.
  11794.  
  11795. Finally, the control record includes a 32-bit reference value field, which is reserved
  11796. for use by your application. You specify an initial reference value when you create a
  11797. control, and can then read or change the reference value whenever you wish.
  11798.  
  11799. The data type for a control record is called ControlRecord. A control record is
  11800. referred to by a handle:
  11801.  
  11802. TYPE  ControlPtr     = ^ControlRecord;
  11803.       ControlHandle  = ^ControlPtr;
  11804.  
  11805. The Control Manager functions for creating a control return a handle to a newly
  11806. allocated control record; thereafter, your program should normally refer to the
  11807. control by this handle. Most of the Control Manager routines expect a control handle
  11808. as their first parameter.
  11809.  
  11810. You can store into and access most of a control record’s fields with Control Manager
  11811. routines, so normally you don’t have to know the exact field names. However, if you
  11812. want more information about the exact structure of a control record—if you’re defining
  11813. your own control types, for instance—it’s given below.
  11814.  
  11815. _______________________________________________________________________________
  11816.  
  11817. »The ControlRecord Data Type
  11818.  
  11819. The ControlRecord data type is defined as follows:
  11820.  
  11821. TYPE ControlRecord =
  11822.       PACKED RECORD
  11823.         nextControl:    ControlHandle;  {next control}
  11824.         contrlOwner:    WindowPtr;      {control's window}
  11825.         contrlRect:     Rect;           {enclosing rectangle}
  11826.         contrlVis:      Byte;           {255 if visible}
  11827.         contrlHilite:   Byte;           {highlight state}
  11828.         contrlValue:    INTEGER;        {control's current setting}
  11829.         contrlMin:      INTEGER;        {control's minimum setting}
  11830.         contrlMax:      INTEGER;        {control's maximum setting}
  11831.         contrlDefProc:  Handle;         {control definition function}
  11832.         contrlData:     Handle;         {data used by contrlDefProc}
  11833.         contrlAction:   ProcPtr;        {default action procedure}
  11834.         contrlRfCon:    LONGINT;        {control's reference value}
  11835.         contrlTitle:    Str255          {control's title}
  11836.       END;
  11837.  
  11838. NextControl is a handle to the next control associated with this control’s window.
  11839. All the controls belonging to a given window are kept in a linked list, beginning in
  11840. the controlList field of the window record and chained together through the nextControl
  11841. fields of the individual control records. The end of the list is marked by a NIL
  11842. value; as new controls are created, they’re added to the beginning of the list.
  11843.  
  11844. ContrlOwner is a pointer to the window that this control belongs to.
  11845.  
  11846. ContrlRect is the rectangle that completely encloses the control, in the local coordinates
  11847. of the control’s window.
  11848.  
  11849. When contrlVis is 0, the control is currently invisible; when it’s 255, the control
  11850. is visible.
  11851.  
  11852. ContrlHilite specifies whether and how the control is to be highlighted, indicating
  11853. whether it’s active or inactive. The HiliteControl procedure lets you set this field;
  11854. see the description of HiliteControl for more information about the meaning of the
  11855. field’s value.
  11856.  
  11857. ContrlValue is the control’s current setting. For check boxes and radio buttons, 0
  11858. means the control is off and 1 means it’s on. For dials, the fields contrlMin and
  11859. contrlMax define the range of possible settings; contrlValue may take on any value
  11860. within that range. Other (custom) control types can use these three fields as they
  11861. see fit.
  11862.  
  11863. ContrlDefProc is a handle to the control definition function for this type of control.
  11864. When you create a control, you identify its type with a control definition ID, which
  11865. is converted into a handle to the control definition function and stored in the
  11866. contrlDefProc field. Thereafter, the Control Manager uses this handle to access the
  11867. definition function; you should never need to refer to this field directly.
  11868.  
  11869. Note:  When not running in 32-bit mode, the high-order byte of the
  11870.        contrlDefProc field contains some additional information that
  11871.        the Control Manager gets from the control definition ID; for
  11872.        details, see the section “Defining Your Own Controls”.
  11873.  
  11874. ContrlData is reserved for use by the control definition function, typically to hold
  11875. additional information specific to a particular control type. For example, the standard
  11876. definition function for scroll bars uses this field for a handle to the region containing
  11877. the scroll bar’s thumb. If no more than four bytes of additional information are
  11878. needed, the definition function can store the information directly in the contrlData
  11879. field rather than use a handle.
  11880.  
  11881. ContrlAction is a pointer to the control’s default action procedure, if any. The
  11882. Control Manager function TrackControl may call this procedure to respond to the
  11883. user’s dragging the mouse inside the control.
  11884.  
  11885. ContrlRfCon is the control’s reference value field, which the application may store
  11886. into and access for any purpose.
  11887.  
  11888. ContrlTitle is the control’s title, if any.
  11889.  
  11890. _______________________________________________________________________________
  11891.  
  11892.  
  11893. æKY Auxiliary…Control…Records
  11894. æC »AUXILIARY CONTROL RECORDS                                  ControlManager
  11895. _______________________________________________________________________________
  11896.  
  11897. The information needed for drawing controls in color is kept in a linked list of
  11898. auxiliary control records, beginning in the global variable AuxCtlHead.
  11899. (Notice that there is just one global list for all controls in all windows, not a
  11900. separate one for each window.) Each window record has a handle to the list of controls.
  11901. Figure 5 shows the auxiliary control list structure.
  11902.  
  11903. •••Refer to Figure 5.•••
  11904.  
  11905. Figure 5–Auxiliary Control List
  11906.  
  11907. Each auxiliary control record is a relocatable object residing in the application
  11908. heap. The most important information it holds is a handle to the control’s individual
  11909. color table (see the “Control Color Tables” section).  The rest of the record consists
  11910. of a link to the next record in the list, a field that identifies the control’s
  11911. owner, a 4-byte field reserved for future expansion, and a 4-byte reference constant
  11912. for use by the application:
  11913.  
  11914. TYPE
  11915.   AuxCtlHandle = ^AuxCtlPtr;
  11916.   AuxCtlPtr    = ^AuxCtlRec;
  11917.   AuxCtlRec    = RECORD
  11918.                    acNext:      AuxCtlHandle;   {handle to next record in list}
  11919.                    acOwner:     ControlHandle;  {handle to owning control}
  11920.                    acCTable:    CCTabHandle;    {handle to control's color }
  11921.                                                 { table}
  11922.                    acFlags:     INTEGER;        {miscellaneous flags; reserved}
  11923.                    acReserved:  LONGINT;        {reserved for future expansion}
  11924.                    acRefCon:    LONGINT         {reserved for application use}
  11925.                  END;
  11926.  
  11927. Field descriptions
  11928.  
  11929. acNext        The acNext field contains a handle to the next record in
  11930.               the auxiliary control list.
  11931.  
  11932. acOwner       The acOwner field contains the handle of the control to
  11933.               which this auxiliary record belongs. Used as an ID field.
  11934.  
  11935. acCTable      The acCTable contains the handle to the control’s color
  11936.               table (see “Control Color Tables” below).
  11937.  
  11938. acFlags       The acFlags field contains miscellaneous flags for use by
  11939.               the Control Manager; this field is reserved.
  11940.  
  11941. acReserved    The acReserved field is reserved for future expansion;
  11942.               this must be set to 0 for future compatibility.
  11943.  
  11944. acRefCon      The acRefCon field is a reference constant for use by
  11945.               the application.
  11946.  
  11947. Not every control needs an auxiliary control record.  When an application is started,
  11948. a resource containing a default color table is loaded from the system resource file;
  11949. this resource defines a standard set of control colors. Since there is no InitControls
  11950. routine, this happens when an application calls InitWindows.
  11951.  
  11952. Separate auxiliary control records are needed only for controls whose color usage
  11953. differs from the default.  Each such nonstandard control must have its own auxiliary
  11954. record, even if it uses the same colors as another control. This allows two or more
  11955. auxiliary records to share the same control color table. If the control color table
  11956. is a resource, it won’t be deleted by DisposeControl. When using an auxiliary record
  11957. that is not stored as a resource, the application should not deallocate the color
  11958. table if another control is still using it.
  11959.  
  11960. A control created from scratch will initially have no auxiliary control record.  If
  11961. it is to use nonstandard colors, it must be given an auxiliary record and a color
  11962. table with SetCtlColor (see the “Control Manager Routines” section).  Such a control
  11963. should normally be made invisible at creation and then displayed with ShowControl
  11964. after the colors are set.  For controls created from a 'CNTL' resource,  the color
  11965. table can be specified as a resource as well. See the section titled “The Control
  11966. Color Table Resource”.
  11967.  
  11968. A/UX systems:  When using 32-bit mode. every control has its own auxiliary
  11969.                record. If there is no specific set of control colors for
  11970.                this control, the acCTable will point to the default color table.
  11971.  
  11972. _______________________________________________________________________________
  11973.  
  11974.  
  11975. æKY Control…Color…Tables
  11976. æC »CONTROL COLOR TABLES                                       ControlManager
  11977. _______________________________________________________________________________
  11978.  
  11979. The contents and meaning of a control’s color table are determined by its control
  11980. definition function (see “The Control Color Table Resource” section). The CTabHandle
  11981. parameter used in the Color Control Manager routines provides a handle to the control
  11982. color table. The components of a control color table are defined as follows:
  11983.  
  11984. TYPE
  11985.   CCTabHandle = ^CCTabPtr;
  11986.   CCTabPtr    = ^CtlCTab;
  11987.   CtlCTab     = RECORD
  11988.                   ccSeed:      LONGINT;    {not used for controls}
  11989.                   ccRider:     INTEGER;    {not used for controls}
  11990.                   ctSize:      INTEGER;    {number of entries in table –1}
  11991.                   ctTable:     cSpecArray  {array of ColorSpec records}
  11992.                 END;
  11993.  
  11994. Field descriptions
  11995.  
  11996. ccSeed        The ccSeed field is unused in control color tables.
  11997.  
  11998. ccRider       The ccRider field is unused in control color tables.
  11999.  
  12000. ctSize        The ctSize field defines the number of elements in the table,
  12001.               minus one. For controls drawn with the standard definition
  12002.               procedure, this field is always 3.
  12003.  
  12004. ctTable       The ctTable field holds an array of colorSpec records. Each
  12005.               colorSpec is made up of a partIdentifier field and a partRGB
  12006.               field. The partIdentifier field holds an integer which
  12007.               associates an RGBColor to a particular part of the control.
  12008.               The definition procedures attempt to find the appropriate part
  12009.               identifier when preparing to draw a part. If that part
  12010.               identifier is not found, the first color in the table is
  12011.               used to draw the part. The part identifiers can appear in any
  12012.               order in the table. The partRGB field specifies a standard RGB
  12013.               color record, indicating what absolute color will be used to
  12014.               draw the control part found in the partIdentifier field.
  12015.  
  12016. A standard control color table is shown in Figure 6.
  12017.  
  12018. •••Refer to Figure 6.•••
  12019.  
  12020. Figure 6–Control Color Table
  12021.  
  12022. The 'cctb' resource is an exact image of this control table data structure, and is
  12023. stored in the same format as 'clut' color table resources.
  12024.  
  12025. Standard buttons, check boxes, and radio buttons use a four-element color table with
  12026. part identifiers as shown below:
  12027.  
  12028.   cFrameColor (0)       Frame color
  12029.   cBodyColor (1)        Fill color for body of control
  12030.   cTextColor (2)        Text color
  12031.   cThumbColor (3)       Unused
  12032.  
  12033. When highlighted, plain buttons exchange their body and text colors (colors 1 and 2);
  12034. check boxes and radio buttons change their appearance without changing colors.  All
  12035. three types indicate deactivation by dimming their text with no change in colors.
  12036.  
  12037. Standard scroll bars use a four-element color table with part identifiers as shown
  12038. below:
  12039.  
  12040.   cFrameColor (0)       Frame color, foreground color for shaft and arrows
  12041.   cBodyColor (1         Background color for shaft and arrows
  12042.   cTextColor (2)        Unused
  12043.   cThumbColor (3)       Fill color for thumb
  12044.  
  12045. When highlighted, the arrows are filled with the foreground color (color 0) within
  12046. the arrow outline. A deactivated scroll bar shows no indicator, and displays its
  12047. shaft in solid background color (color 1), with no pattern.
  12048.  
  12049. The 'cctb' resource = 0 is read into the application heap when the application starts,
  12050. and serves as the default control color table. The last record in the auxiliary
  12051. control list points to the default 'cctb' resource. When drawing a control, the
  12052. standard control definition function searches the list for an auxiliary control
  12053. record whose acOwner points to the control being drawn.  If it finds such a record,
  12054. it uses the color table designated by that record; if it doesn’t find one before
  12055. reaching the default record at the end of the list, it uses the default color table
  12056. instead. All types of controls share the same default record. The default auxiliary
  12057. control record is recognized by NIL values in both its acNext and acOwner fields; the
  12058. application must not change these fields.
  12059.  
  12060. A nonstandard control definition function can use color tables of any desired size
  12061. and define their contents in any way it wishes, except that part indices 1 to 127 are
  12062. reserved for system definition.  Any such nonstandard function should take care to
  12063. bypass the defaulting mechanism just described, by allocating an explicit auxiliary
  12064. record for every control it creates.
  12065.  
  12066. _______________________________________________________________________________
  12067.  
  12068.  
  12069. æKY The…Control…Color…Table…Resource
  12070. æC »THE CONTROL COLOR TABLE RESOURCE                           ControlManager
  12071. _______________________________________________________________________________
  12072.  
  12073. The system default control colors are stored in the System file and ROMResources as
  12074. 'cctb' resource = 0. By including a 'cctb' resource = 0 in your application, it is
  12075. possible to change the default colors that will be used for all controls, unless a
  12076. specific 'cctb' exists for a control defined within the application.
  12077.  
  12078. When you use GetNewControl for the control resource 'CNTL', GetNewControl will attempt
  12079. to load a 'cctb' resource with the same ID as the 'CNTL' resource ID, if one is
  12080. present. It then executes the SetCtlColor call.
  12081.  
  12082. The following part identifiers for control elements should be present in the ColorSpec.value
  12083. field:
  12084.  
  12085.   cFrameColor (0)       Frame color
  12086.   cBodyColor (1)        Fill color for body of control
  12087.   cTextColor (2)        Text color
  12088.   cThumbColor (3)       Thumb color
  12089.  
  12090. These identifiers may be present in any order; for instance, the text or indicator
  12091. color values may be stored before the fill and frame colors in the ColorSpec record
  12092. structure. If a part identifier is not found, then the first color in the color table
  12093. will be used.
  12094.  
  12095. _______________________________________________________________________________
  12096.  
  12097.  
  12098. æKY Using…the…Control…Manager
  12099. æC »USING THE CONTROL MANAGER                                  ControlManager
  12100. _______________________________________________________________________________
  12101.  
  12102. To use the Control Manager, you must have previously called InitGraf to initialize
  12103. QuickDraw, InitFonts to initialize the Font Manager, and InitWindows to initialize
  12104. the Window Manager.
  12105.  
  12106. Note:  For controls in dialogs or alerts, the Dialog Manager makes some
  12107.        of the basic Control Manager calls for you; see the Dialog Manager
  12108.        chapter for more information.
  12109.  
  12110. Where appropriate in your program, use NewControl or GetNewControl to create any
  12111. controls you need. NewControl takes descriptive information about the new control
  12112. from its parameters; GetNewControl gets the information from a control template in a
  12113. resource file. When you no longer need a control, call DisposeControl to remove it
  12114. from its window’s control list and release the memory it occupies. To dispose of all
  12115. of a given window’s controls at once, use KillControls.
  12116.  
  12117. Note:  The Window Manager procedures DisposeWindow and CloseWindow
  12118.        automatically dispose of all the controls associated with the
  12119.        given window.
  12120.  
  12121. When the Toolbox Event Manager function GetNextEvent reports that an update event has
  12122. occurred for a window, the application should call DrawControls to redraw the window’s
  12123. controls as part of the process of updating the window.
  12124.  
  12125. After receiving a mouse-down event from GetNextEvent, do the following:
  12126.  
  12127.   1.  First call FindWindow to determine which part of which window the
  12128.       mouse button was pressed in.
  12129.  
  12130.   2.  If it was in the content region of the active window, call FindControl
  12131.       for that window to find out whether it was in an active control, and
  12132.       if so, in which part of which control.
  12133.  
  12134.   3.  Finally, take whatever action is appropriate when the user presses
  12135.       the mouse button in that part of the control, using routines such
  12136.       as TrackControl (to perform some action repeatedly for as long as
  12137.       the mouse button is down, or to allow the user to drag the control’s
  12138.       indicator with the mouse), DragControl (to pull an outline of the
  12139.       control across the screen and move the control to a new location),
  12140.       and HiliteControl (to change the way the control is highlighted).
  12141.  
  12142. For the standard control types, step 3 involves calling TrackControl. TrackControl
  12143. handles the highlighting of the control and determines whether the mouse is still in
  12144. the control when the mouse button is released. It also handles the dragging of the
  12145. thumb in a scroll bar and, via your action procedure, the response to presses or
  12146. clicks in the other parts of a scroll bar. When TrackControl returns the part code
  12147. for a button, check box, or radio button, the application must do whatever is appropriate
  12148. as a response to a click of that control. When TrackControl returns the part code for
  12149. the thumb of a scroll bar, the application must scroll to the corresponding relative
  12150. position in the document.
  12151.  
  12152. The application’s exact response to mouse activity in a control that retains a setting
  12153. will depend on the current setting of the control, which is available from the GetCtlValue
  12154. function. For controls whose values can be set by the user, the SetCtlValue procedure
  12155. may be called to change the control’s setting and redraw the control accordingly.
  12156. You’ll call SetCtlValue, for example, when a check box or radio button is clicked, to
  12157. change the setting and draw or clear the mark inside the control.
  12158.  
  12159. Wherever needed in your program, you can call HideControl to make a control invisible
  12160. or ShowControl to make it visible. Similarly, MoveControl, which simply changes a
  12161. control’s location without pulling around an outline of it, can be called at any
  12162. time, as can SizeControl, which changes its size. For example, when the user changes
  12163. the size of a document window that contains a scroll bar, you’ll call HideControl to
  12164. remove the old scroll bar, MoveControl and SizeControl to change its location and
  12165. size, and ShowControl to display it as changed.
  12166.  
  12167. Whenever necessary, you can read various attributes of a control with GetCTitle,
  12168. GetCtlMin, GetCtlMax, GetCRefCon, or GetCtlAction; you can change them with SetCTitle,
  12169. SetCtlMin, SetCtlMax, SetCRefCon, or SetCtlAction.
  12170.  
  12171. _______________________________________________________________________________
  12172.  
  12173.  
  12174. æKY Using…Color…Controls
  12175. æC »USING COLOR CONTROLS                                       ControlManager
  12176. _______________________________________________________________________________
  12177.  
  12178. The following caveats apply to the use of color with controls:
  12179.  
  12180.   •  Controls are drawn in the window port, which by default is an
  12181.      old-style GrafPort. This limits color matching to the eight old
  12182.      QuickDraw colors. To achieve full RGB display with controls, the
  12183.      window must be opened as a cGrafPort, using NewCWindow, GetNewCWindow,
  12184.      or any other window routine that creates a color window.
  12185.  
  12186. Since there is no “InitControls” call, a default AuxCtlRec is created and intialized
  12187. on the application heap when InitWindows is executed. When a new control is created
  12188. with the NewControl routine, no entry is added to the AuxList, and the control will
  12189. use the default colors. If SetCtlColor is used with a different color set of a control,
  12190. a new AuxList will be allocated and added to the head of the list. The CloseControl
  12191. routine disposes of the AuxCtlRec.
  12192.  
  12193. Often a new control is created from a 'CNTL' resource, using GetNewControl. A new
  12194. AuxRec is allocated if the resource file contains a 'cctb' resource type with the
  12195. same resource ID as the 'CNTL' resource. Otherwise, the default colors are used.
  12196.  
  12197. The Control Manager supports controls that have color tables with more than four
  12198. elements. To create a control with more than four colors, you must create a custom
  12199. 'CDEF' that can access a larger color table.The interpretation of the partIdentifiers
  12200. is determined by the 'CDEF'. If  your application includes a
  12201. 'CDEF' that recognizes more than four partIdentifiers, it should use partIdentifiers
  12202. 0–3 in the same way as the standard control defprocs. An application with a custom
  12203. 'CDEF" should use the _SysEnvirons routine upon entry to the defproc to determine the
  12204. configuration of the system.
  12205.  
  12206. _______________________________________________________________________________
  12207.  
  12208.  
  12209. æKY Control…Manager…Routines
  12210. æC »CONTROL MANAGER ROUTINES                                   ControlManager
  12211. _______________________________________________________________________________
  12212.  
  12213. »Initialization and Allocation
  12214.  
  12215. FUNCTION NewControl (theWindow:  WindowPtr; boundsRect:  Rect; title:  Str255;
  12216.                      visible:  BOOLEAN; value:  INTEGER; min,max:  INTEGER;
  12217.                      procID:  INTEGER; refCon:  LONGINT) :  ControlHandle;
  12218.  
  12219. NewControl creates a control, adds it to the beginning of theWindow’s control list,
  12220. and returns a handle to the new control. The values passed as parameters are stored
  12221. in the corresponding fields of the control record, as described below. The field that
  12222. determines highlighting is set to 0 (no highlighting) and the pointer to the default
  12223. action procedure is set to NIL (none).
  12224.  
  12225. Note:  The control definition function may do additional initialization,
  12226.        including changing any of the fields of the control record. The only
  12227.        standard control for which additional initialization is done is the
  12228.        scroll bar; its control definition function allocates space for a
  12229.        region to hold the thumb and stores the region handle in the
  12230.        contrlData field of the control record.
  12231.  
  12232. TheWindow is the window the new control will belong to. All coordinates pertaining to
  12233. the control will be interpreted in this window’s local coordinate system.
  12234.  
  12235. BoundsRect, given in theWindow’s local coordinates, is the rectangle that encloses
  12236. the control and thus determines its size and location. Note the following about the
  12237. enclosing rectangle for the standard controls:
  12238.  
  12239.   •  Simple buttons are drawn to fit the rectangle exactly. (The control
  12240.      definition function calls the QuickDraw procedure FrameRoundRect.) To
  12241.      allow for the tallest characters in the system font, there should be
  12242.      at least a 20-point difference between the top and bottom coordinates
  12243.      of the rectangle.
  12244.   •  For check boxes and radio buttons, there should be at least a 16-point
  12245.      difference between the top and bottom coordinates.
  12246.   •  By convention, scroll bars are 16 pixels wide, so there should be a
  12247.      16-point difference between the left and right (or top and bottom)
  12248.      coordinates. (If there isn’t, the scroll bar will be scaled to fit
  12249.      the rectangle.) A standard scroll bar should be at least 48 pixels
  12250.      long, to allow room for the scroll arrows and thumb.
  12251.  
  12252. Title is the control’s title, if any (if none, you can just pass the empty string as
  12253. the title). Be sure the title will fit in the control’s enclosing rectangle; if it
  12254. won’t it will be truncated on the right for check boxes and radio buttons, or centered
  12255. and truncated on both ends for simple buttons.
  12256.  
  12257. Note:  Some non-Roman systems write text from right-to-left, in which
  12258.        case radio buttons and check boxes are drawn with their titles
  12259.        on the left of the control.  They are also truncated on the left.
  12260.        See the Script Manager chapter for more information.
  12261.  
  12262. If the visible parameter is TRUE, NewControl draws the control.
  12263.  
  12264. Note:  It does not use the standard window updating mechanism, but
  12265.        instead draws the control immediately in the window.
  12266.  
  12267. The min and max parameters define the control’s range of possible settings; the value
  12268. parameter gives the initial setting. For controls that don’t retain a setting, such
  12269. as buttons, the values you supply for these parameters will be stored in the control
  12270. record but will never be used. So it doesn’t matter what values you give for those
  12271. controls—0 for all three parameters will do. For controls that just retain an on-or-off
  12272. setting, such as check boxes or radio buttons, min should be 0 (meaning the control
  12273. is off) and max should be 1
  12274. (meaning it’s on). For dials, you can specify whatever values are appropriate for
  12275. min, max, and value.
  12276.  
  12277. ProcID is the control definition ID, which leads to the control definition function
  12278. for this type of control. (The function is read into memory if it
  12279. isn’t already in memory.) The control definition IDs for the standard control types
  12280. are listed above under “Controls and Resources”. Control definition IDs for custom
  12281. control types are discussed later under “Defining Your Own Controls”.
  12282.  
  12283. RefCon is the control’s reference value, set and used only by your application.
  12284.  
  12285. FUNCTION GetNewControl (controlID:  INTEGER;
  12286.                         theWindow:  WindowPtr) :  ControlHandle;
  12287.  
  12288. GetNewControl creates a control from a control template stored in a resource file,
  12289. adds it to the beginning of theWindow’s control list, and returns a handle to the new
  12290. control. ControlID is the resource ID of the template. GetNewControl works exactly
  12291. the same as NewControl (above), except that it gets the initial values for the new
  12292. control’s fields from the specified control template instead of accepting them as
  12293. parameters. If the control template can’t be read from the resource file, GetNewControl
  12294. returns NIL. It releases the memory occupied by the resource before returning.
  12295.  
  12296. PROCEDURE DisposeControl (theControl:  ControlHandle);
  12297.  
  12298. Assembly-language note:  The macro you invoke to call DisposeControl from
  12299.                          assembly language is named _DisposControl.
  12300.  
  12301. DisposeControl removes theControl from the screen, deletes it from its window’s
  12302. control list, and releases the memory occupied by the control record and any data
  12303. structures associated with the control.
  12304.  
  12305. PROCEDURE KillControls (theWindow:  WindowPtr);
  12306.  
  12307. KillControls disposes of all controls associated with theWindow by calling DisposeControl
  12308. (above) for each.
  12309.  
  12310. Note:  Remember that the Window Manager procedures CloseWindow and
  12311.        DisposeWindow automatically dispose of all controls associated
  12312.        with the given window.
  12313.  
  12314. _______________________________________________________________________________
  12315.  
  12316. »Control Display
  12317.  
  12318. These procedures affect the appearance of a control but not its size or location.
  12319.  
  12320. PROCEDURE SetCTitle (theControl:  ControlHandle; title:  Str255);
  12321.  
  12322. SetCTitle sets theControl’s title to the given string and redraws the control.
  12323.  
  12324. PROCEDURE GetCTitle (theControl:  ControlHandle; VAR title:  Str255);
  12325.  
  12326. GetCTitle returns theControl’s title as the value of the title parameter.
  12327.  
  12328. PROCEDURE HideControl (theControl:  ControlHandle);
  12329.  
  12330. HideControl makes theControl invisible. It fills the region the control occupies
  12331. within its window with the background pattern of the window’s grafPort. It also adds
  12332. the control’s enclosing rectangle to the window’s update region, so that anything
  12333. else that was previously obscured by the control will reappear on the screen. If the
  12334. control is already invisible, HideControl has no effect.
  12335.  
  12336. PROCEDURE ShowControl (theControl:  ControlHandle);
  12337.  
  12338. ShowControl makes theControl visible. The control is drawn in its window but may be
  12339. completely or partially obscured by overlapping windows or other objects. If the
  12340. control is already visible, ShowControl has no effect.
  12341.  
  12342. PROCEDURE DrawControls (theWindow:  WindowPtr);
  12343.  
  12344. DrawControls draws all controls currently visible in theWindow. The controls are
  12345. drawn in reverse order of creation; thus in case of overlap the earliest-created
  12346. controls appear frontmost in the window.
  12347.  
  12348. Note:  Window Manager routines such as SelectWindow, ShowWindow, and
  12349.        BringToFront do not automatically call DrawControls to display
  12350.        the window’s controls. They just add the appropriate regions to
  12351.        the window’s update region, generating an update event. Your program
  12352.        should always call DrawControls explicitly upon receiving an update
  12353.        event for a window that contains controls.
  12354.  
  12355. PROCEDURE Draw1Control (theControl:  ControlHandle); [128K ROM]
  12356.  
  12357. Draw1Control draws the specified control if it’s visible within the window.
  12358.  
  12359. PROCEDURE UpdtControl (theWindow:  WindowPtr; updateRgn:  RgnHandle); [128K ROM]
  12360.  
  12361. UpdtControl is a faster version of the DrawControls procedure. Instead of drawing all
  12362. of the controls in theWindow, UpdtControl draws only the controls that are in the
  12363. specified update region. UpdtControl is called in response to an update event, and is
  12364. usually bracketed by calls to the Window Manager procedures BeginUpdate and EndUpdate.
  12365. UpdateRgn should be set to the visRgn of theWindow’s port (for more details, see the
  12366. BeginUpdate procedure in the Window Manager chapter).
  12367.  
  12368. Note:  In general, controls are in a dialog box and are automatically
  12369.        drawn by the DrawDialog procedure.
  12370.  
  12371. PROCEDURE HiliteControl (theControl:  ControlHandle; hiliteState:  INTEGER);
  12372.  
  12373. HiliteControl changes the way theControl is highlighted. HiliteState has one of the
  12374. following values:
  12375.  
  12376.   •  The value 0 means no highlighting. (The control is active.)
  12377.   •  A value between 1 and 253 is interpreted as a part code designating
  12378.      the part of the (active) control to be highlighted.
  12379.   •  The value 255 means that the control is to be made inactive and
  12380.      highlighted accordingly.
  12381.  
  12382. Note:  The value 254 should not be used; this value is reserved for future use.
  12383.  
  12384. HiliteControl calls the control definition function to redraw the control with its
  12385. new highlighting.
  12386.  
  12387. _______________________________________________________________________________
  12388.  
  12389. »Mouse Location
  12390.  
  12391. FUNCTION FindControl (thePoint:  Point; theWindow:  WindowPtr; VAR whichControl: 
  12392. ControlHandle) :  INTEGER;
  12393.  
  12394. When the Window Manager function FindWindow reports that the mouse button was pressed
  12395. in the content region of a window, and the window contains controls, the application
  12396. should call FindControl with theWindow equal to the window pointer and thePoint equal
  12397. to the point where the mouse button was pressed (in the window’s local coordinates).
  12398. FindControl tells which of the window’s controls, if any, the mouse button was pressed
  12399. in:
  12400.  
  12401.   •  If it was pressed in a visible, active control, FindControl sets the
  12402.      whichControl parameter to the control handle and returns a part code
  12403.      identifying the part of the control that it was pressed in.
  12404.   •  If it was pressed in an invisible or inactive control, or not in any
  12405.      control, FindControl sets whichControl to NIL and returns 0 as its result.
  12406.  
  12407. Warning:  Notice that FindControl expects the mouse point in the window’s
  12408.           local coordinates, whereas FindWindow expects it in global
  12409.           coordinates. Always be sure to convert the point to local
  12410.           coordinates with the QuickDraw procedure GlobalToLocal before
  12411.           calling FindControl.
  12412.  
  12413. Note:  FindControl also returns NIL for whichControl and 0 as its result
  12414.        if the window is invisible or doesn’t contain the given point. In
  12415.        these cases, however, FindWindow wouldn’t have returned this window
  12416.        in the first place, so the situation should never arise.
  12417.  
  12418. FUNCTION TrackControl (theControl:  ControlHandle; startPt:  Point;
  12419.                        actionProc:  ProcPtr) :  INTEGER;
  12420.  
  12421. When the mouse button is pressed in a visible, active control, the application should
  12422. call TrackControl with theControl equal to the control handle and startPt equal to
  12423. the point where the mouse button was pressed (in the local coordinates of the control’s
  12424. window). TrackControl follows the movements of the mouse and responds in whatever way
  12425. is appropriate until the mouse button is released; the exact response depends on the
  12426. type of control and the part of the control in which the mouse button was pressed. If
  12427. highlighting is appropriate, TrackControl does the highlighting, and undoes it before
  12428. returning. When the mouse button is released, TrackControl returns with the part code
  12429. if the mouse is in the same part of the control that it was originally in, or with 0
  12430. if not
  12431. (in which case the application should do nothing).
  12432.  
  12433. If the mouse button was pressed in an indicator, TrackControl drags a dotted outline
  12434. of it to follow the mouse. When the mouse button is released, TrackControl calls the
  12435. control definition function to reposition the control’s indicator. The control definition
  12436. function for scroll bars responds by redrawing the thumb, calculating the control’s
  12437. current setting based on the new relative position of the thumb, and storing the
  12438. current setting in the control record; for example, if the minimum and maximum settings
  12439. are 0 and 10, and the thumb is in the middle of the scroll bar, 5 is stored as the
  12440. current setting. The application must then scroll to the corresponding relative
  12441. position in the document.
  12442.  
  12443. TrackControl may take additional actions beyond highlighting the control or dragging
  12444. the indicator, depending on the value passed in the actionProc parameter, as described
  12445. below. The following tells you what to pass for the standard control types; for a
  12446. custom control, what you pass will depend on how the control is defined.
  12447.  
  12448.   •  If actionProc is NIL, TrackControl performs no additional actions. This
  12449.      is appropriate for simple buttons, check boxes, radio buttons, and the
  12450.      thumb of a scroll bar.
  12451.   •  ActionProc may be a pointer to an action procedure that defines some
  12452.      action to be performed repeatedly for as long as the user holds down
  12453.      the mouse button. (See below for details.)
  12454.   •  If actionProc is POINTER(–1), TrackControl looks in the control record
  12455.      for a pointer to the control’s default action procedure. If that field
  12456.      of the control record contains a procedure pointer, TrackControl uses
  12457.      the action procedure it points to; if the field contains POINTER (–1),
  12458.      TrackControl calls the control definition function to perform the
  12459.      necessary action. (If the field contains NIL, TrackControl does nothing.)
  12460.  
  12461. The action procedure in the control definition function is described in the section
  12462. “Defining Your Own Controls”. The following paragraphs describe only the action
  12463. procedure whose pointer is passed in the actionProc parameter or stored in the control
  12464. record.
  12465.  
  12466. If the mouse button was pressed in an indicator, the action procedure (if any) should
  12467. have no parameters. This procedure must allow for the fact that the mouse may not be
  12468. inside the original control part.
  12469.  
  12470. If the mouse button was pressed in a control part other than an indicator, the action
  12471. procedure should be of the form
  12472.  
  12473. PROCEDURE MyAction (theControl:  ControlHandle; partCode:  INTEGER);
  12474.  
  12475. In this case, TrackControl passes the control handle and the part code to the action
  12476. procedure. (It passes 0 in the partCode parameter if the mouse has moved outside the
  12477. original control part.) As an example of this type of action procedure, consider what
  12478. should happen when the mouse button is pressed in a scroll arrow or paging region in
  12479. a scroll bar. For these cases, your action procedure should examine the part code to
  12480. determine exactly where the mouse button was pressed, scroll up or down a line or
  12481. page as appropriate, and call SetCtlValue to change the control’s setting and redraw
  12482. the thumb.
  12483.  
  12484. Warning:  Since it has a different number of parameters depending on whether
  12485.           the mouse button was pressed in an indicator or elsewhere, the
  12486.           action procedure you pass to TrackControl (or whose pointer you
  12487.           store in the control record) can be set up for only one case or
  12488.           the other. If you store a pointer to a default action procedure
  12489.           in a control record, be sure it will be used only when appropriate
  12490.           for that type of action procedure. The only way to specify actions
  12491.           in response to all mouse-down events in a control, regardless of
  12492.           whether they’re in an indicator, is via the control definition
  12493.           function.
  12494.  
  12495. Assembly-language note:  If you store a pointer to a procedure in the global
  12496.                          variable DragHook, that procedure will be called
  12497.                          repeatedly (with no parameters) for as long as the
  12498.                          user holds down the mouse button. TrackControl
  12499.                          invokes the Window Manager macro _DragTheRgn,
  12500.                          which calls the DragHook procedure. _DragTheRgn
  12501.                          uses the pattern stored in the global variable
  12502.                          DragPattern for the dragged outline of the indicator.
  12503.  
  12504. FUNCTION TestControl (theControl:  ControlHandle; thePoint:  Point) :  INTEGER;
  12505.  
  12506. If theControl is visible and active, TestControl tests which part of the control
  12507. contains thePoint (in the local coordinates of the control’s window); it returns the
  12508. corresponding part code, or 0 if the point is outside the control. If the control is
  12509. invisible or inactive, TestControl returns 0. TestControl is called by FindControl
  12510. and TrackControl; normally you won’t need to call it yourself.
  12511.  
  12512. _______________________________________________________________________________
  12513.  
  12514. »Control Movement and Sizing
  12515.  
  12516. PROCEDURE MoveControl (theControl:  ControlHandle; h,v:  INTEGER);
  12517.  
  12518. MoveControl moves theControl to a new location within its window. The top left corner
  12519. of the control’s enclosing rectangle is moved to the horizontal and vertical coordinates
  12520. h and v (given in the local coordinates of the control’s window); the bottom right
  12521. corner is adjusted accordingly, to keep the size of the rectangle the same as before.
  12522. If the control is currently visible, it’s hidden and then redrawn at its new location.
  12523.  
  12524. PROCEDURE DragControl (theControl:  ControlHandle; startPt:  Point;
  12525.                        limitRect,slopRect:  Rect; axis:  INTEGER);
  12526.  
  12527. Called with the mouse button down inside theControl, DragControl pulls a dotted
  12528. outline of the control around the screen, following the movements of the mouse until
  12529. the button is released. When the mouse button is released, DragControl calls MoveControl
  12530. to move the control to the location to which it was dragged.
  12531.  
  12532. Note:  Before beginning to follow the mouse, DragControl calls the control
  12533.        definition function to allow it to do its own “custom dragging” if
  12534.        it chooses. If the definition function doesn’t choose to do any
  12535.        custom dragging, DragControl uses the default method of dragging
  12536.        described here.
  12537.  
  12538. The startPt, limitRect, slopRect, and axis parameters have the same meaning as for
  12539. the Window Manager function DragGrayRgn. These parameters are reviewed briefly below;
  12540. see the description of DragGrayRgn in the Window Manager chapter for more details.
  12541.  
  12542.   •  StartPt is assumed to be the point where the mouse button was originally
  12543.      pressed, in the local coordinates of the control’s window.
  12544.   •  LimitRect limits the travel of the control’s outline, and should normally
  12545.      coincide with or be contained within the window’s content region.
  12546.   •  SlopRect allows the user some “slop” in moving the mouse; it should
  12547.      completely enclose limitRect.
  12548.   •  The axis parameter allows you to constrain the control’s motion to
  12549.      only one axis. It has one of the following values:
  12550.  
  12551.        CONST  noConstraint = 0;    {no constraint}
  12552.               hAxisOnly    = 1;    {horizontal axis only}
  12553.               vAxisOnly    = 2;    {vertical axis only}
  12554.  
  12555. Assembly-language note:  Like TrackControl, DragControl invokes the
  12556.                          macro _DragTheRgn, so you can use the global
  12557.                          variables DragHook and DragPattern.
  12558.  
  12559. PROCEDURE SizeControl (theControl:  ControlHandle; w,h:  INTEGER);
  12560.  
  12561. SizeControl changes the size of theControl’s enclosing rectangle. The bottom right
  12562. corner of the rectangle is adjusted to set the rectangle’s width and height to the
  12563. number of pixels specified by w and h; the position of the top left corner is not
  12564. changed. If the control is currently visible, it’s hidden and then redrawn in its new
  12565. size.
  12566.  
  12567. _______________________________________________________________________________
  12568.  
  12569. »Control Setting and Range
  12570.  
  12571. PROCEDURE SetCtlValue (theControl:  ControlHandle; theValue:  INTEGER);
  12572.  
  12573. SetCtlValue sets theControl’s current setting to theValue and redraws the control to
  12574. reflect the new setting. For check boxes and radio buttons, the value 1 fills the
  12575. control with the appropriate mark, and 0 clears it. For scroll bars, SetCtlValue
  12576. redraws the thumb where appropriate.
  12577.  
  12578. If the specified value is out of range, it’s forced to the nearest endpoint of the
  12579. current range (that is, if theValue is less than the minimum setting, SetCtlValue
  12580. sets the current setting to the minimum; if theValue is greater than the maximum
  12581. setting, it sets the current setting to the maximum).
  12582.  
  12583. FUNCTION GetCtlValue (theControl:  ControlHandle) :  INTEGER;
  12584.  
  12585. GetCtlValue returns theControl’s current setting.
  12586.  
  12587. PROCEDURE SetCtlMin (theControl:  ControlHandle; minValue:  INTEGER);
  12588.  
  12589. Assembly-language note:  The macro you invoke to call SetCtlMin from
  12590.                          assembly language is named _SetMinCtl.
  12591.  
  12592. SetCtlMin sets theControl’s minimum setting to minValue and redraws the control to
  12593. reflect the new range. If the control’s current setting is less than minValue, the
  12594. setting is changed to the new minimum.
  12595.  
  12596. FUNCTION GetCtlMin (theControl:  ControlHandle) :  INTEGER;
  12597.  
  12598. Assembly-language note:  The macro you invoke to call GetCtlMin from
  12599.                          assembly language is named _GetMinCtl.
  12600.  
  12601. GetCtlMin returns theControl’s minimum setting.
  12602.  
  12603. PROCEDURE SetCtlMax (theControl:  ControlHandle; maxValue:  INTEGER);
  12604.  
  12605. Assembly-language note:  The macro you invoke to call SetCtlMax from
  12606.                          assembly language is named _SetMaxCtl.
  12607.  
  12608. SetCtlMax sets theControl’s maximum setting to maxValue and redraws the control to
  12609. reflect the new range. If the control’s current setting is greater than maxValue, the
  12610. setting is changed to the new maximum.
  12611.  
  12612. Note:  If you set the maximum setting of a scroll bar equal to its minimum
  12613.        setting, the control definition function will make the scroll bar
  12614.        inactive.
  12615.  
  12616. FUNCTION GetCtlMax (theControl:  ControlHandle) :  INTEGER;
  12617.  
  12618. Assembly-language note:  The macro you invoke to call GetCtlMax from
  12619.                          assembly language is named _GetMaxCtl.
  12620.  
  12621. GetCtlMax returns theControl’s maximum setting.
  12622.  
  12623. _______________________________________________________________________________
  12624.  
  12625. »Miscellaneous Routines
  12626.  
  12627. PROCEDURE SetCRefCon (theControl:  ControlHandle; data:  LONGINT);
  12628.  
  12629. SetCRefCon sets theControl’s reference value to the given data.
  12630.  
  12631. FUNCTION GetCRefCon (theControl:  ControlHandle) :  LONGINT;
  12632.  
  12633. GetCRefCon returns theControl’s current reference value.
  12634.  
  12635. PROCEDURE SetCtlAction (theControl:  ControlHandle; actionProc:  ProcPtr);
  12636.  
  12637. SetCtlAction sets theControl’s default action procedure to actionProc.
  12638.  
  12639. FUNCTION GetCtlAction (theControl:  ControlHandle) :  ProcPtr;
  12640.  
  12641. GetCtlAction returns a pointer to theControl’s default action procedure, if any. (It
  12642. returns whatever is in that field of the control record.)
  12643.  
  12644. The following new Control Manager routines can be used as noted below for the Macintosh
  12645. Plus, the Macintosh SE, and the Macintosh II.
  12646.  
  12647. FUNCTION GetCVariant (theControl: ControlHandle) : INTEGER;
  12648. [Macintosh Plus, Macintosh SE, and Macintosh II]
  12649.  
  12650. The GetVariant function returns the variant control value for the control described
  12651. by theControl. This value was formerly stored in the high four bits of the control
  12652. defproc handle; for future compatibility, use the GetCVariant routine to access this
  12653. value.
  12654.  
  12655. PROCEDURE SetCtlColor (theControl: ControlHandle; newColorTable: CCTabHandle);
  12656. [Macintosh II]
  12657.  
  12658. The SetCtlColor procedure sets or modifies a control’s color table.  If the control
  12659. currently has no auxiliary control record, a new one is created with the given color
  12660. table and added to the head of the auxiliary control list. If there is already an
  12661. auxiliary record for the control, its color table is replaced by the contents of
  12662. newColorTable.
  12663.  
  12664. If newColorTable has the same contents as the default color table, the
  12665. control’s existing auxiliary record and color table are removed from the auxiliary
  12666. control list and deallocated.  If theControl = NIL, the operation modifies the default
  12667. color table itself. If the control is visible, it will be redrawn by SetCtlColor
  12668. using the new color table.
  12669.  
  12670. FUNCTION GetAuxCtl (theControl: ControlHandle;
  12671.                     VAR acHndl: AuxCtlHandle) : BOOLEAN; [Macintosh II]
  12672.  
  12673. The GetAuxCtl function returns a handle to a control’s AuxCtlRec:
  12674.  
  12675.   •  If the given control has its own color table, the function returns TRUE.
  12676.   •  If the control used the default color set, the function returns FALSE.
  12677.   •  If the control asked to receive the default color set (theControl = NIL),
  12678.      then the function returns TRUE.
  12679.  
  12680. _______________________________________________________________________________
  12681.  
  12682.  
  12683. æKY Defining…Your…Own…Controls
  12684. æC »DEFINING YOUR OWN CONTROLS
  12685. _______________________________________________________________________________
  12686.  
  12687. In addition to the standard, built-in control types (buttons, check boxes, radio
  12688. buttons, and scroll bars), the Control Manager allows you to define
  12689. “custom” control types of your own. Maybe you need a three-way selector switch, a
  12690. memory-space indicator that looks like a thermometer, or a thruster control for a
  12691. spacecraft simulator—whatever your application calls for. Controls and their indicators
  12692. may occupy regions of any shape, in the full generality permitted by QuickDraw.
  12693.  
  12694. To define your own type of control, you write a control definition function and store
  12695. it in a resource file. When you create a control, you provide a control definition
  12696. ID, which leads to the control definition function. The control definition ID is an
  12697. integer that contains the resource ID of the control definition function in its upper
  12698. 12 bits and a variation code in its lower four bits. Thus, for a given resource ID
  12699. and variation code, the control definition ID is
  12700.  
  12701.   16 * resource ID + variation code
  12702.  
  12703. For example, buttons, check boxes, and radio buttons all use the standard definition
  12704. function whose resource ID is 0, but they have variation codes of 0, 1, and 2, respectively.
  12705.  
  12706. The Control Manager calls the Resource Manager to access the control definition
  12707. function with the given resource ID. The Resource Manager reads the control definition
  12708. function into memory and returns a handle to it. The Control Manager stores this
  12709. handle in the contrlDefProc field of the control record.  In 24-bit addressing mode,
  12710. the variation code is placed in the high-order byte of this field; in 32-bit mode,
  12711. the variation code is placed in the most significant byte of the acReserved field in
  12712. the control’s AuxCtlRec.  Later, when it needs to perform a type-dependent action on
  12713. the control, it calls the control definition function and passes it the variation
  12714. code as a parameter. Figure 7 illustrates this process.
  12715.  
  12716. Keep in mind that the calls your application makes to use a control depend heavily on
  12717. the control definition function. What you pass to the TrackControl function, for
  12718. example, depends on whether the definition function contains an action procedure for
  12719. the control. Just as you need to know how to call TrackControl for the standard
  12720. controls, each custom control type will have a particular calling protocol that must
  12721. be followed for the control to work properly.
  12722.  
  12723. _______________________________________________________________________________
  12724.  
  12725. »The Control Definition Function
  12726.  
  12727. The control definition function is usually written in assembly language, but may be
  12728. written in Pascal.
  12729.  
  12730. •••Refer to Figure 7.•••
  12731.  
  12732. Figure 7–Control Definition Handling
  12733.  
  12734. Assembly-language note:  The function’s entry point must be at the beginning.
  12735.  
  12736. You can give your control definition function any name you like. Here’s how you would
  12737. declare one named MyControl:
  12738.  
  12739. FUNCTION MyControl (varCode:  INTEGER; theControl:  ControlHandle;
  12740.                     message:  INTEGER; param:  LONGINT) :  LONGINT;
  12741.  
  12742. VarCode is the variation code, as described above.
  12743.  
  12744. TheControl is a handle to the control that the operation will affect.
  12745.  
  12746. The message parameter identifies the desired operation. It has one of the following
  12747. values:
  12748.  
  12749. CONST  drawCntl   = 0;    {draw the control (or control part)}
  12750.        testCntl   = 1;    {test where mouse button was pressed}
  12751.        calcCRgns  = 2;    {calculate control's region (or indicator's)}
  12752.        initCntl   = 3;    {do any additional control initialization}
  12753.        dispCntl   = 4;    {take any additional disposal actions}
  12754.        posCntl    = 5;    {reposition control's indicator and update it}
  12755.        thumbCntl  = 6;    {calculate parameters for dragging indicator}
  12756.        dragCntl   = 7;    {drag control (or its indicator)}
  12757.        autoTrack  = 8;    {execute control's action procedure}
  12758.  
  12759. As described below in the discussions of the routines that perform these operations,
  12760. the value passed for param, the last parameter of the control definition function,
  12761. depends on the operation. Where it’s not mentioned below, this parameter is ignored.
  12762. Similarly, the control definition function is expected to return a function result
  12763. only where indicated; in other cases, the function should return 0.
  12764.  
  12765. In some cases, the value of param or the function result is a part code. The part
  12766. code 128 is reserved for future use and shouldn’t be used for parts of your controls.
  12767. Part codes greater than 128 should be used for indicators; however, 129 has special
  12768. meaning to the control definition function, as described below.
  12769.  
  12770. Note:  “Routine” here doesn’t necessarily mean a procedure or function.
  12771.        While it’s a good idea to set these up as subprograms inside the
  12772.        control definition function, you’re not required to do so.
  12773.  
  12774. A new version of the control definition function (version 4 or greater) in the 128K
  12775. ROM allows buttons, check boxes, and radio buttons to have multiple lines of text in
  12776. their titles. When specifying the title with either NewControl or SetCTitle, simply
  12777. separate the lines with the ASCII character code $0D
  12778. (carriage return). You can also use a version of the Resource Editor that supports
  12779. the 128K ROM to specify multiline titles.
  12780.  
  12781. Note:  This feature will work with the 64K ROM if the new version of
  12782.        the control definition function is in the system resource file.
  12783.  
  12784. If the control is a button, each line is horizontally centered and separated from the
  12785. neighboring lines by the font’s leading. (Since the height of each line is equal to
  12786. the ascent plus descent plus leading of the font used, be sure to make the total
  12787. height of the enclosing rectangle greater than the number of lines times this height.)
  12788.  
  12789. If the control is a check box or a radio button, the text is left-justified and the
  12790. check box or button is vertically centered within the enclosing rectangle, cntrlRect.
  12791.  
  12792. Note:  The text is right-justified on check boxes and radio buttons if
  12793.        running under a non-Roman system that draws text from right-to-left.
  12794.        See the Script Manager chapter for more information.
  12795. _______________________________________________________________________________
  12796.  
  12797. »The Draw Routine
  12798.  
  12799. The message drawCntl asks the control definition function to draw all or part of the
  12800. control within its enclosing rectangle. The value of param is a part code specifying
  12801. which part of the control to draw, or 0 for the entire control. If the control is
  12802. invisible (that is, if its contrlVis field is 0), there’s nothing to do; if it’s
  12803. visible, the definition function should draw it (or the requested part), taking into
  12804. account the current values of its contrlHilite and contrlValue fields. The control
  12805. may be either scaled or clipped to the enclosing rectangle.
  12806.  
  12807. If param is the part code of the control’s indicator, the draw routine can assume
  12808. that the indicator hasn’t moved; it might be called, for example, to highlight the
  12809. indicator. There’s a special case, though, in which the draw routine has to allow for
  12810. the fact that the indicator may have moved:  This happens when the Control Manager
  12811. procedures SetCtlValue, SetCtlMin, and SetCtlMax call the control definition function
  12812. to redraw the indicator after changing the control setting. Since they have no way of
  12813. knowing what part code you chose for your indicator, they all pass 129 to mean the
  12814. indicator. The draw routine must detect this part code as a special case, and remove
  12815. the indicator from its former location before drawing it.
  12816.  
  12817. Note:  If your control has more than one indicator, 129 should be
  12818.        interpreted to mean all indicators.
  12819.  
  12820. _______________________________________________________________________________
  12821.  
  12822. »The Test Routine
  12823.  
  12824. The Control Manager function FindControl sends the message testCntl to the control
  12825. definition function when the mouse button is pressed in a visible control. This
  12826. message asks in which part of the control, if any, a given point lies. The point is
  12827. passed as the value of param, in the local coordinates of the control’s window; the
  12828. vertical coordinate is in the high-order word of the long integer and the horizontal
  12829. coordinate is in the low-order word. The control definition function should return
  12830. the part code for the part of the control that contains the point; it should return 0
  12831. if the point is outside the control or if the control is inactive.
  12832.  
  12833. _______________________________________________________________________________
  12834.  
  12835. »The Routine to Calculate Regions
  12836.  
  12837. The control definition function should respond to the message calcCRgns by calculating
  12838. the region the control occupies within its window. Param is a QuickDraw region handle;
  12839. the definition function should update this region to the region occupied by the
  12840. control, expressed in the local coordinate system of its window.
  12841.  
  12842. If the high-order bit of param is set, the region requested is that of the control’s
  12843. indicator rather than the control as a whole. The definition function should clear
  12844. the high bit of the region handle before attempting to update the region.
  12845.  
  12846. _______________________________________________________________________________
  12847.  
  12848. »The Initialize Routine
  12849.  
  12850. After initializing fields as appropriate when creating a new control, the Control
  12851. Manager sends the message initCntl to the control definition function. This gives the
  12852. definition function a chance to perform any type-specific initialization it may
  12853. require. For example, if you implement the control’s action procedure in its control
  12854. definition function, you’ll set up the initialize routine to store POINTER(–1) in the
  12855. contrlAction field; TrackControl calls for this control would pass POINTER(–1) in the
  12856. actionProc parameter.
  12857.  
  12858. The control definition function for scroll bars allocates space for a region to hold
  12859. the scroll bar’s thumb and stores the region handle in the contrlData field of the
  12860. new control record. The initialize routine for standard buttons, check boxes, and
  12861. radio buttons does nothing.
  12862.  
  12863. _______________________________________________________________________________
  12864.  
  12865. »The Dispose Routine
  12866.  
  12867. The Control Manager’s DisposeControl procedure sends the message dispCntl to the
  12868. control definition function, telling it to carry out any additional actions required
  12869. when disposing of the control. For example, the standard definition function for
  12870. scroll bars releases the space occupied by the thumb region, whose handle is kept in
  12871. the control’s contrlData field. The dispose routine for standard buttons, check
  12872. boxes, and radio buttons does nothing.
  12873.  
  12874. _______________________________________________________________________________
  12875.  
  12876. »The Drag Routine
  12877.  
  12878. The message dragCntl asks the control definition function to drag the control or its
  12879. indicator around on the screen to follow the mouse until the user releases the mouse
  12880. button. Param specifies whether to drag the indicator or the whole control:  0 means
  12881. drag the whole control, while a nonzero value means drag only the indicator.
  12882.  
  12883. The control definition function need not implement any form of “custom
  12884. dragging”; if it returns a result of 0, the Control Manager will use its own default
  12885. method of dragging (calling DragControl to drag the control or the Window Manager
  12886. function DragGrayRgn to drag its indicator). Conversely, if the control definition
  12887. function chooses to do its own custom dragging, it should signal the Control Manager
  12888. not to use the default method by returning a nonzero result.
  12889.  
  12890. If the whole control is being dragged, the definition function should call MoveControl
  12891. to reposition the control to its new location after the user releases the mouse
  12892. button. If just the indicator is being dragged, the definition function should execute
  12893. its own position routine (see below) to update the control’s setting and redraw it in
  12894. its window.
  12895.  
  12896. _______________________________________________________________________________
  12897.  
  12898. »The Position Routine
  12899.  
  12900. For controls that don’t use the Control Manager’s default method of dragging the
  12901. control’s indicator (as performed by DragGrayRgn), the control definition function
  12902. must include a position routine. When the mouse button is released inside the indicator
  12903. of such a control, TrackControl calls the control definition function with the message
  12904. posCntl to reposition the indicator and update the control’s setting accordingly. The
  12905. value of param is a point giving the vertical and horizontal offset, in pixels, by
  12906. which the indicator is to be moved relative to its current position. (Typically, this
  12907. is the offset between the points where the user pressed and released the mouse button
  12908. while dragging the indicator.) The vertical offset is given in the high-order word of
  12909. the long integer and the horizontal offset in the low-order word. The definition
  12910. function should calculate the control’s new setting based on the given offset, update
  12911. the contrlValue field, and redraw the control within its window to reflect the new
  12912. setting.
  12913.  
  12914. Note:  The Control Manager procedures SetCtlValue, SetCtlMin, and SetCtlMax
  12915.        do not call the control definition function with this message; instead,
  12916.        they pass the drawCntl message to execute the draw routine (see above).
  12917.  
  12918. _______________________________________________________________________________
  12919.  
  12920. »The Thumb Routine
  12921.  
  12922. Like the position routine, the thumb routine is required only for controls that don’t
  12923. use the Control Manager’s default method of dragging the control’s indicator. The
  12924. control definition function for such a control should respond to the message thumbCntl
  12925. by calculating the limiting rectangle, slop rectangle, and axis constraint for dragging
  12926. the control’s indicator. Param is a pointer to the following data structure:
  12927.  
  12928.   RECORD
  12929.     limitRect,slopRect:  Rect;
  12930.     axis:  INTEGER
  12931.   END;
  12932.  
  12933. On entry, param^.limitRect.topLeft contains the point where the mouse button was
  12934. first pressed. The definition function should store the appropriate values into the
  12935. fields of the record pointed to by param; they’re analogous to the similarly named
  12936. parameters to DragGrayRgn.
  12937.  
  12938. _______________________________________________________________________________
  12939.  
  12940. »The Track Routine
  12941.  
  12942. You can design a control to have its action procedure in the control definition
  12943. function. To do this, set up the control’s initialize routine to store
  12944. POINTER(–1) in the contrlAction field of the control record, and pass
  12945. POINTER(–1) in the actionProc parameter to TrackControl. TrackControl will respond by
  12946. calling the control definition function with the message autoTrack. The definition
  12947. function should respond like an action procedure, as discussed in detail in the
  12948. description of TrackControl. It can tell which part of the control the mouse button
  12949. was pressed in from param, which contains the part code. The track routine for each
  12950. of the standard control types does nothing.
  12951.  
  12952. _______________________________________________________________________________
  12953.  
  12954.  
  12955. æKY Formats…of…Resources…for…Controls
  12956. æC »FORMATS OF RESOURCES FOR CONTROLS
  12957. _______________________________________________________________________________
  12958.  
  12959. The GetNewControl function takes the resource ID of a control template as a parameter,
  12960. and gets from that template the same information that the NewControl function gets
  12961. from eight of its parameters. The resource type for a control template is 'CNTL', and
  12962. the resource data has the following format:
  12963.  
  12964.   Number of bytes    Contents
  12965.  
  12966.   8 bytes            Same as boundsRect parameter to NewControl
  12967.   2 bytes            Same as value parameter to NewControl
  12968.   2 bytes            Same as visible parameter to NewControl
  12969.   2 bytes            Same as max parameter to NewControl
  12970.   2 bytes            Same as min parameter to NewControl
  12971.   2 bytes            Same as procID parameter to NewControl
  12972.   4 bytes            Same as refCon parameter to NewControl
  12973.   n bytes            Same as title parameter to NewControl
  12974.                      (1-byte length in bytes, followed by the
  12975.                      characters of the title)
  12976.  
  12977. The resource type for a control definition function is 'CDEF'. The resource data is
  12978. simply the compiled or assembled code of the function.
  12979.  
  12980. _______________________________________________________________________________
  12981.  
  12982.  
  12983. æKY Summary…of…the…Control…Manager
  12984. æC »SUMMARY OF THE CONTROL MANAGER
  12985. _______________________________________________________________________________
  12986.  
  12987. Constants
  12988.  
  12989. CONST
  12990.  
  12991.   { Control definition IDs }
  12992.  
  12993.   pushButProc    = 0;    {simple button}
  12994.   checkBoxProc   = 1;    {check box}
  12995.   radioButProc   = 2;    {radio button}
  12996.   useWFont       = 8;    {add to above to use window's font}
  12997.   scrollBarProc  = 16;   {scroll bar}
  12998.  
  12999.   { Part codes }
  13000.  
  13001.   inButton      = 10;    {simple button}
  13002.   inCheckBox    = 11;    {check box or radio button}
  13003.   inUpButton    = 20;    {up arrow of a scroll bar}
  13004.   inDownButton  = 21;    {down arrow of a scroll bar}
  13005.   inPageUp      = 22;    {"page up" region of a scroll bar}
  13006.   inPageDown    = 23;    {"page down" region of a scroll bar}
  13007.   inThumb       = 129;   {thumb of a scroll bar}
  13008.  
  13009.   { Axis constraints for DragControl }
  13010.  
  13011.   noConstraint  = 0;     {no constraint}
  13012.   hAxisOnly     = 1;     {horizontal axis only}
  13013.   vAxisOnly     = 2;     {vertical axis only}
  13014.  
  13015.   { Messages to control definition function }
  13016.  
  13017.   drawCntl   = 0;    {draw the control (or control part)}
  13018.   testCntl   = 1;    {test where mouse button was pressed}
  13019.   calcCRgns  = 2;    {calculate control's region (or indicator's)}
  13020.   initCntl   = 3;    {do any additional control initialization}
  13021.   dispCntl   = 4;    {take any additional disposal actions}
  13022.   posCntl    = 5;    {reposition control's indicator and update it}
  13023.   thumbCntl  = 6;    {calculate parameters for dragging indicator}
  13024.   dragCntl   = 7;    {drag control (or its indicator)}
  13025.   autoTrack  = 8;    {execute control's action procedure}
  13026.  
  13027.   { Control part colors }
  13028.  
  13029.   cFrameColor  =  0;
  13030.   cBodyColor   =  1;
  13031.   cTextColor   =  2;
  13032.   cThumbColor  =  3;
  13033.  
  13034. _______________________________________________________________________________
  13035.  
  13036. Data Types
  13037.  
  13038. TYPE
  13039.   ControlPtr     = ^ControlRecord;
  13040.   ControlHandle  = ^ControlPtr;
  13041.   ControlRecord  =
  13042.       PACKED RECORD
  13043.         nextControl:    ControlHandle;  {next control}
  13044.         contrlOwner:    WindowPtr;      {control's window}
  13045.         contrlRect:     Rect;           {enclosing rectangle}
  13046.         contrlVis:      Byte;           {255 if visible}
  13047.         contrlHilite:   Byte;           {highlight state}
  13048.         contrlValue:    INTEGER;        {control's current setting}
  13049.         contrlMin:      INTEGER;        {control's minimum setting}
  13050.         contrlMax:      INTEGER;        {control's maximum setting}
  13051.         contrlDefProc:  Handle;         {control definition function}
  13052.         contrlData:     Handle;         {data used by contrlDefProc}
  13053.         contrlAction:   ProcPtr;        {default action procedure}
  13054.         contrlRfCon:    LONGINT;        {control's reference value}
  13055.         contrlTitle:    Str255          {control's title}
  13056.       END;
  13057.  
  13058.   AuxCtlHandle = ^AuxCtlPtr;
  13059.   AuxCtlPtr    = ^AuxCtlRec;
  13060.   AuxCtlRec    = RECORD
  13061.                    acNext:      AuxCtlHandle;   {handle to next record in list}
  13062.                    acOwner:     ControlHandle;  {handle to owning control}
  13063.                    acCTable:    CCTabHandle;    {handle to control's color }
  13064.                                                 { table}
  13065.                    acFlags:     INTEGER;        {miscellaneous flags; reserved}
  13066.                    acReserved:  LONGINT;        {reserved for future expansion}
  13067.                    acRefCon:    LONGINT         {reserved for application use}
  13068.                  END;
  13069.  
  13070.   CCTabHandle = ^CCTabPtr;
  13071.   CCTabPtr    = ^CtlCTab;
  13072.   CtlCTab     = RECORD
  13073.                   ccSeed:      LONGINT;    {not used for controls}
  13074.                   ccRider:     INTEGER;    {not used for controls}
  13075.                   ctSize:      INTEGER;    {number of entries in table –1}
  13076.                   ctTable:     cSpecArray  {array of ColorSpec records}
  13077.                 END;
  13078.  
  13079. _______________________________________________________________________________
  13080.  
  13081. Routines
  13082.  
  13083. Initialization and Allocation
  13084.  
  13085. FUNCTION  NewControl     (theWindow:  WindowPtr; boundsRect:  Rect;
  13086.                           title:  Str255; visible:  BOOLEAN; value:  INTEGER;
  13087.                           min,max:  INTEGER; procID:  INTEGER;
  13088.                           refCon:  LONGINT) :  ControlHandle;
  13089. FUNCTION  GetNewControl  (controlID:  INTEGER;
  13090.                           theWindow:  WindowPtr) :  ControlHandle;
  13091. PROCEDURE DisposeControl (theControl:  ControlHandle);
  13092. PROCEDURE KillControls   (theWindow:  WindowPtr);
  13093.  
  13094. Control Display
  13095.  
  13096. PROCEDURE SetCTitle      (theControl:  ControlHandle; title:  Str255);
  13097. PROCEDURE GetCTitle      (theControl:  ControlHandle; VAR title:  Str255);
  13098. PROCEDURE HideControl    (theControl:  ControlHandle);
  13099. PROCEDURE ShowControl    (theControl:  ControlHandle);
  13100. PROCEDURE DrawControls   (theWindow:  WindowPtr);
  13101. PROCEDURE Draw1Control   (theControl:  ControlHandle); [128K ROM]
  13102. PROCEDURE UpdtControl    (theWindow:  WindowPtr;
  13103.                           updateRgn:  RgnHandle); [128K ROM]
  13104. PROCEDURE HiliteControl  (theControl:  ControlHandle; hiliteState:  INTEGER);
  13105.  
  13106. Mouse Location
  13107.  
  13108. FUNCTION FindControl   (thePoint:  Point; theWindow:  WindowPtr;
  13109.                         VAR whichControl:  ControlHandle) :  INTEGER;
  13110. FUNCTION TrackControl  (theControl:  ControlHandle; startPt:  Point;
  13111.                         actionProc:  ProcPtr) :  INTEGER;
  13112. FUNCTION TestControl   (theControl:  ControlHandle;
  13113.                         thePoint:  Point) :  INTEGER;
  13114.  
  13115. Control Movement and Sizing
  13116.  
  13117. PROCEDURE MoveControl  (theControl:  ControlHandle; h,v:  INTEGER);
  13118. PROCEDURE DragControl  (theControl:  ControlHandle; startPt:  Point;
  13119.                         limitRect,slopRect:  Rect; axis:  INTEGER);
  13120. PROCEDURE SizeControl  (theControl:  ControlHandle; w,h:  INTEGER);
  13121.  
  13122. Control Setting and Range
  13123.  
  13124. PROCEDURE SetCtlValue  (theControl:  ControlHandle; theValue:  INTEGER);
  13125. FUNCTION  GetCtlValue  (theControl:  ControlHandle) :  INTEGER;
  13126. PROCEDURE SetCtlMin    (theControl:  ControlHandle; minValue:  INTEGER);
  13127. FUNCTION  GetCtlMin    (theControl:  ControlHandle) :  INTEGER;
  13128. PROCEDURE SetCtlMax    (theControl:  ControlHandle; maxValue INTEGER);
  13129. FUNCTION  GetCtlMax    (theControl:  ControlHandle) :  INTEGER;
  13130.  
  13131. Miscellaneous Routines
  13132.  
  13133. PROCEDURE SetCRefCon    (theControl:  ControlHandle; data:  LONGINT);
  13134. FUNCTION  GetCRefCon    (theControl:  ControlHandle) :  LONGINT;
  13135. PROCEDURE SetCtlAction  (theControl:  ControlHandle; actionProc ProcPtr);
  13136. FUNCTION  GetCtlAction  (theControl:  ControlHandle) :  ProcPtr;
  13137. PROCEDURE SetCtlColor   (theControl:  ControlHandle;
  13138.                          newColorTable: CCTabHandle);
  13139. FUNCTION  GetAuxCtl     (theControl:  ControlHandle;
  13140.                          VAR acHndl: AuxWinHandle): BOOLEAN;
  13141. FUNCTION  GetCVariant   (theControl: ControlHandle) : INTEGER;
  13142.  
  13143. _______________________________________________________________________________
  13144.  
  13145. Action Procedure for TrackControl
  13146.  
  13147. If an indicator:      PROCEDURE MyAction;
  13148. If not an indicator:  PROCEDURE MyAction (theControl:  ControlHandle;
  13149.                                           partCode:  INTEGER);
  13150.  
  13151. _______________________________________________________________________________
  13152.  
  13153. Control Definition Function
  13154.  
  13155. FUNCTION MyControl (varCode:  INTEGER; theControl:  ControlHandle;
  13156.                     message:  INTEGER; param:  LONGINT) :  LONGINT;
  13157.  
  13158. _______________________________________________________________________________
  13159.  
  13160. Global Variables
  13161.  
  13162. AuxWinHead    Contains a pointer to the linked list of auxiliary
  13163.               control records.
  13164.  
  13165. _______________________________________________________________________________
  13166.  
  13167. Assembly-Language Information
  13168.  
  13169. Constants
  13170.  
  13171. ; Control definition IDs
  13172.  
  13173. pushButProc    .EQU  0   ;simple button
  13174. checkBoxProc   .EQU  1   ;check box
  13175. radioButProc   .EQU  2   ;radio button
  13176. useWFont       .EQU  8   ;add to above to use window's font
  13177. scrollBarProc  .EQU  16  ;scroll bar
  13178.  
  13179. ; Part codes
  13180.  
  13181. inButton       .EQU  10  ;simple button
  13182. inCheckBox     .EQU  11  ;check box or radio button
  13183. inUpButton     .EQU  20  ;up arrow of a scroll bar
  13184. inDownButton   .EQU  21  ;down arrow of a scroll bar
  13185. inPageUp       .EQU  22  ;"page up" region of a scroll bar
  13186. inPageDown     .EQU  23  ;"page down" region of a scroll bar
  13187. inThumb        .EQU  129 ;thumb of a scroll bar
  13188.  
  13189. ; Axis constraints for DragControl
  13190.  
  13191. noConstraint   .EQU  0   ;no constraint
  13192. hAxisOnly      .EQU  1   ;horizontal axis only
  13193. vAxisOnly      .EQU  2   ;vertical axis only
  13194.  
  13195. ; Messages to control definition function
  13196.  
  13197. drawCtlMsg     .EQU  0   ;draw the control (or control part)
  13198. hitCtlMsg      .EQU  1   ;test where mouse button was pressed
  13199. calcCtlMsg     .EQU  2   ;calculate control's region (or indicator's)
  13200. newCtlMsg      .EQU  3   ;do any additional control initialization
  13201. dispCtlMsg     .EQU  4   ;take any additional disposal actions
  13202. posCtlMsg      .EQU  5   ;reposition control's indicator and update it
  13203. thumbCtlMsg    .EQU  6   ;calculate parameters for dragging indicator
  13204. dragCtlMsg     .EQU  7   ;drag control (or its indicator)
  13205. trackCtlMsg    .EQU  8   ;execute control's action procedure
  13206.  
  13207. ;auxCtlRec structure
  13208.  
  13209. acnext          EQU   $0  ;[handle] next in chain
  13210. acOwner         EQU   $4  ;[ControlHandle] owner ID
  13211. acCTable        EQU   $8  ;[CTabHandle] color table
  13212. acFlags         EQU   $C  ;[word] miscellaneous flags
  13213. acReserved      EQU   $E  ;[LONGINT] for expansion
  13214. acRefCon        EQU   $18 ;[LONGINT] user constant
  13215. auxWinSize      EQU   $1C ;size of record
  13216.  
  13217. ; Equates for the colors of control parts
  13218.  
  13219. cFrameColor     EQU    0         
  13220. cBodyColor      EQU    1         
  13221. cTextColor      EQU    2         
  13222. cThumbColor     EQU    3         
  13223.  
  13224. ; Global variable
  13225.  
  13226. AuxCtlHead      EQU    $0CD4    ;Control Aux List head
  13227.  
  13228. Control Record Data Structure
  13229.  
  13230. nextControl      Handle to next control in control list
  13231. contrlOwner      Pointer to this control’s window
  13232. contrlRect       Control’s enclosing rectangle (8 bytes)
  13233. contrlVis        255 if control is visible (byte)
  13234. contrlHilite     Highlight state (byte)
  13235. contrlValue      Control’s current setting (word)
  13236. contrlMin        Control’s minimum setting (word)
  13237. contrlMax        Control’s maximum setting (word)
  13238. contrlDefHandle  Handle to control definition function
  13239. contrlData       Data used by control definition function (long)
  13240. contrlAction     Address of default action procedure
  13241. contrlRfCon      Control’s reference value (long)
  13242. contrlTitle      Handle to control’s title (preceded by length byte)
  13243. contrlSize       Size in bytes of control record except contrlTitle field
  13244.  
  13245. Special Macro Names
  13246.  
  13247. Pascal name       Macro name
  13248.  
  13249. DisposeControl    _DisposControl
  13250. GetCtlMax         _GetMaxCtl
  13251. GetCtlMin         _GetMinCtl
  13252. SetCtlMax         _SetMaxCtl
  13253. SetCtlMin         _SetMinCtl
  13254.  
  13255. Variables
  13256.  
  13257. DragHook     Address of procedure to execute during TrackControl
  13258.              and DragControl
  13259. DragPattern  Pattern of dragged region’s outline (8 bytes)
  13260.  
  13261. Further Reference:
  13262. _______________________________________________________________________________
  13263. Resource Manager
  13264. QuickDraw
  13265. Toolbox Event Manager
  13266. Window Manager
  13267. Script Manager
  13268. Technical Note #196, 'CDEF' Parameters and Bugs
  13269. Technical Note #212, The Joy Of Being 32-Bit Clean
  13270.  
  13271. æKY ControlPanels
  13272. æC 
  13273. _______________________________________________________________________________
  13274.  
  13275. CONTROL PANELS
  13276. _______________________________________________________________________________
  13277.  
  13278. About…the…Control…Panels…Chapter
  13279. About…Control…Panels
  13280. About…the…Monitors…Control…Panel
  13281. Writing…Control…Panel…Files
  13282. Designing…an…Extension…for…the…Monitors…Control…Panel
  13283.     Contents…of…an…Extension…File…for…the…Monitors…Control…Panel
  13284.     'card'…Resource
  13285.     'mntr'…Resource
  13286.     The…Mntr…Function
  13287.     Messages…to…the…Mntr…Function
  13288.     Error-Handling…by…the…Mntr…Function
  13289.     'DITL'…Resource
  13290.     'RECT'…Resource
  13291.     'ICON'…and…'cicn'…Resources
  13292.     'STR#'…Resource
  13293.     'gama'…Resources
  13294.     'FREF',…'BNDL',…'ICN#',…and…Owner…Resources
  13295.     'INIT'…Resource
  13296.     Sample…of…a…File…That…Extends…the…Monitors…Control…Panel
  13297.     Including…Another…Control…Panel…Definition…in…a…Monitors…Extension
  13298. Summary…of…the…Extension…File…for…the…Monitors…Control…Panel
  13299.     Control…Panels…Constants
  13300.     Control…Panels…Routines
  13301. _______________________________________________________________________________
  13302.  
  13303.  
  13304.  
  13305. æKY About…the…Control…Panels…Chapter
  13306. æC »ABOUT THIS CHAPTER                                                      Control Panels
  13307. _______________________________________________________________________________
  13308.  
  13309. All versions of the Macintosh Operating System previous to system software
  13310. version 7.0 provide a desk accessory called the Control Panel. The Control Panel
  13311. allows users to control certain system features, such as speaker volume, date
  13312. and time, and desktop pattern. With the release of System file version 4.1,
  13313. documented in Volume V, the Control Panel became extensible by the addition of
  13314. control panel extension files (files of file type 'cdev') to the System Folder.
  13315. The contents and operation of control panel extension files are described in the
  13316. Control Panel chapter of Volume V. 
  13317.  
  13318. In system software version 7.0, the Control Panel, as a discrete desk accessory,
  13319. has been eliminated. Instead, the Finder can now open each file of file type
  13320. 'cdev'. The panel defined by the control panel file, which had been part of the
  13321. Control Panel, is now an independent dialog box. 
  13322.  
  13323. This chapter describes how to write a control panel file that is compatible with
  13324. both the old Control Panel and with version 7.0, and how to write an extension
  13325. for the Monitors control panel file. 
  13326.  
  13327. In this chapter, the dialog box defined by a file of file type 'cdev' is
  13328. referred to as a control panel (as opposed to the Control Panel), and the file
  13329. itself is referred to as a control panel file. 
  13330.  
  13331. Only the manufacturer of a video device should write an extension to the
  13332. Monitors control panel for that device. Therefore, if you are not developing a
  13333. video card for the Macintosh computer, you do not need the information in this
  13334. chapter on the Monitors control panel.
  13335.  
  13336. _______________________________________________________________________________
  13337.  
  13338. æKY About…Control…Panels
  13339. æC »ABOUT CONTROL PANELS                                                    Control Panels
  13340. _______________________________________________________________________________
  13341.  
  13342. Under system software version 7.0, the user sees little difference between a
  13343. control panel and a small application. The main reason to create a control panel
  13344. file rather than an application is to maintain compatibility with the Control
  13345. Panel for users who are using older operating systems. Any control panel file
  13346. that follows the rules and suggestions given in the Control Panel chapter of
  13347. Volume V will continue to work without problems under version 7.0. 
  13348. Control panels open in the Finder layer. The user can store control panels in
  13349. either the Control Panels folder, the Apple Menu folder in the System Folder, or
  13350. any other location in the file system.
  13351.  
  13352. You should refer to a file of type 'cdev' as a control panel file in any user
  13353. documentation that you provide. Don’t pass on the file type name of this file or
  13354. any other file to users. 
  13355. _______________________________________________________________________________
  13356.  
  13357. æKY About…the…Monitors…Control…Panel
  13358. æC »ABOUT THE MONITORS CONTROL PANEL                                        Control Panels
  13359. _______________________________________________________________________________
  13360.  
  13361. The Monitors control panel file that is provided with system software version
  13362. 7.0 is extensible. The developer of a video card can add items to the Monitors
  13363. control panel that allow users to control features of the video device.
  13364.  
  13365. The Monitors control panel file displays a control panel that allows a user to 
  13366.  
  13367.   •   select which one of the monitors connected to the system should display
  13368.       the menu bar
  13369.   •   select which monitor the system should use as a startup screen
  13370.   •   inform the Operating System about the relative locations of the monitors
  13371.   •   control some features of the monitors, such as whether a color monitor
  13372.       displays in color or in black and white, or the number of colors or
  13373.       gray-scale values to display
  13374.  
  13375. Figure 9-1 shows an example of the Monitors control panel. 
  13376.  
  13377. ø 9.1  The Monitors control panel
  13378.  
  13379. As Figure 9-1 illustrates, the Monitors control panel now includes a button
  13380. labeled Options; when the user clicks this button, another panel appears with
  13381. additional controls. When you add an extension to the Monitors control panel,
  13382. the controls you add appear in the Options dialog box. Figure 9-2 shows an
  13383. example of an Options dialog box for the Monitors control panel. 
  13384.  
  13385. ø 9.2  A sample Options dialog box for a Monitors control panel
  13386.  
  13387. _______________________________________________________________________________
  13388.  
  13389. æKY Writing…Control…Panel…Files
  13390. æC »WRITING CONTROL PANEL FILES                                             Control Panels
  13391. _______________________________________________________________________________
  13392.  
  13393. You should keep the following points in mind if you are writing or modifying a
  13394. control panel file:
  13395.  
  13396.   •   A control panel file displays a modeless dialog box with no menu bar. You
  13397.       can use the editing functions in the menu bar put up by the Finder if
  13398.       necessary, but you cannot add any menu choices. The Finder passes
  13399.       messages to your cdev function for the following standard selections from
  13400.       the Edit menu: undo, cut, copy, paste, and clear. Your cdev function can
  13401.       respond to these messages when it is appropriate to do so; for example,
  13402.       if your control panel has an editable input field, you can respond to
  13403.       these editing functions when the cursor is within this field.
  13404.  
  13405.   •   The rectangles defined by the 'nrct' resource are no longer restricted to
  13406.       the size of the Control Panel; however, to maintain compatibility with
  13407.       previous operating systems, the rectangles’ coordinates should not exceed
  13408.       (–1, 87, 255, 322).
  13409.  
  13410.   •   There is no longer a guarantee that the resources provided by the Control
  13411.       Panel are available when your control panel file is running. If your
  13412.       control panel file uses any Control Panel resources, it might not run
  13413.       under version 7.0. If your control panel file strictly follows the
  13414.       specifications in the Control Panel chapter of Volume V, however, it
  13415.       should run with no difficulty under version 7.0.
  13416.  
  13417.   •   Your control panel file can continue to use the CPDialog parameter passed
  13418.       to the cdev function to obtain the dialog items list and the numItems
  13419.       parameter to determine the number of items in the dialog items list. If
  13420.       you use these parameters in your control panel file to gain access to the
  13421.       items in your dialog items list, your control panel file will operate
  13422.       correctly with both the Control Panel and the Finder. If you assume some
  13423.       value for the numItems parameter, however, your control panel file will
  13424.       not operate correctly in both situations. Dialog items lists are
  13425.       described in the Dialog Manager chapter of Volume I.
  13426.  
  13427.   •   If the 'mach' resource in your control panel file indicates that the cdev
  13428.       function cannot run, the Finder displays an error message for the user
  13429.       and does not open the control panel file. In contrast, the Control Panel
  13430.       does not display the icon for a control panel file if the 'mach' resource
  13431.       indicates the cdev function cannot run. If your control panel file can
  13432.       run on all Macintosh computers, set the 'mach' resource to $FFFF 0000. If
  13433.       your control panel file can run only if certain hardware or software are
  13434.       present, set the 'mach' resource to $0000 FFFF. In the latter case, the
  13435.       Finder calls your cdev function with the message parameter set to macDev
  13436.       (8). Your cdev function should then call the Gestalt function to
  13437.       determine the software and hardware configuration of the machine. If your
  13438.       control panel file cannot run, return a result code of 0; if your control
  13439.       panel file can run, return a result code of 1. The Gestalt function is
  13440.       described in the Compatibility Guidelines chapter.
  13441.  
  13442.   •   Result codes returned by your cdev function are now handled by the
  13443.       Finder. Whereas the Control Panel grays out the icon for a control panel
  13444.       file in response to certain result codes, the Finder displays an error
  13445.       message but does not gray out the control panel file icon.
  13446.  
  13447. _______________________________________________________________________________
  13448.  
  13449. æKY Designing…an…Extension…for…the…Monitors…Control…Panel
  13450. æC »DESIGNING AN EXTENSION FOR THE MONITORS CONTROL PANEL                   Control Panels
  13451. _______________________________________________________________________________
  13452.  
  13453. The maker of a video card can provide a file of type 'cdev' that adds controls
  13454. to the Options dialog box. An extension to the Monitors control panel should
  13455. control features of the video card only; a Monitors extension should not control
  13456. system features. For example, a Monitors control panel extension might allow the
  13457. user to set the virtual screen size for a single monitor, but not to set the
  13458. size of the menu bar, which can appear on any monitor.
  13459.  
  13460. Because the Options dialog box is called from another dialog box, it is not
  13461. advisable to write an extension that puts up yet another dialog box. If the
  13462. features that you want to implement require an extensive or complex set of
  13463. controls, it would be better to write a small application rather than an
  13464. extension to the Monitors control panel file.
  13465.  
  13466. †  Warning:  Only the manufacturer of the video card should write an extension
  13467. to the Monitors control panel file. There can be only one extension to the
  13468. Monitors control panel file for each video card. Apple Computer, Inc., reserves
  13469. the right to write control panel files for its own video cards. Ê 
  13470. _______________________________________________________________________________
  13471.  
  13472. æKY Contents…of…an…Extension…File…for…the…Monitors…Control…Panel
  13473. æC »Contents of an Extension File for the Monitors Control Panel            Control Panels
  13474. _______________________________________________________________________________
  13475.  
  13476. The extension file for the Monitors control panel must be a file of type 'cdev'
  13477. containing at least the following resources:
  13478.  
  13479.   •   'card'  (ID can be any number from –4080 through –4065)
  13480.   •   'mntr'  (ID = –4096)
  13481.   •   'DITL'  (ID = –4096)
  13482.   •   'RECT'  (ID = –4096)
  13483.  
  13484. Your Monitors extension file can also include any of the following resources:
  13485.  
  13486.   •   'ICON'  (ID = –4096)
  13487.   •   'cicn'  (ID = –4096)
  13488.   •   'STR#'  (ID = –4096)
  13489.   •   'gama'  (ID can be any number from –4080 through –4065) 
  13490.   •   'FREF'
  13491.   •    'BNDL'
  13492.   •   'ICN#'
  13493.   •   'INIT'
  13494.   •   owner resource
  13495.  
  13496. These resources are described in the following sections. You can use resource ID
  13497. numbers of –4080 through –4065 for any private resources in your Monitors
  13498. extension.
  13499.  
  13500. _______________________________________________________________________________
  13501.  
  13502. æKY 'card'…Resource
  13503. æC »'card' Resource                                                         Control Panels
  13504. _______________________________________________________________________________
  13505.  
  13506. The 'card' resource contains a Pascal string (that is, a length byte followed by
  13507. an ASCII string) identical to the name of a video card as returned by the Slot
  13508. Manager’s SReadDrvrName function (minus the period that the Slot Manager
  13509. prefixes to the name). The extension file can contain as many 'card' resources
  13510. as you wish, so that one extension file can handle several versions of one video
  13511. card. The Options dialog box displays the name in the 'card' resource unless you
  13512. also include a 'STR#' resource in the extension file, as described in “'STR#'
  13513. Resource” later in this chapter. The Slot Manager chapter in Volume V describes
  13514. the SReadDrvrName function.
  13515.  
  13516. _______________________________________________________________________________
  13517.  
  13518. æKY 'mntr'…Resource
  13519. æC »'mntr' Resource                                                         Control Panels
  13520. _______________________________________________________________________________
  13521.  
  13522. The 'mntr' resource contains the code that carries out the functions of your
  13523. Monitors extension. This resource must begin with a Mntr function that you must
  13524. provide. The parameters passed to the Mntr function by the Monitors control
  13525. panel allow your code to determine what action to perform. You can use the
  13526. function result to keep a handle to local storage or to return an error code.
  13527. These options are described in the sections “Parameter Descriptions” and
  13528. “Error-Handling by the Mntr Function,” later in this chapter.
  13529.  
  13530. _______________________________________________________________________________
  13531.  
  13532. æKY The…Mntr…Function
  13533. æC »The Mntr Function                                                       Control Panels
  13534. _______________________________________________________________________________
  13535.  
  13536. The 'mntr' resource must contain a function, referred to as a Mntr function, to
  13537. respond to the various events that can occur while the Options dialog box is on
  13538. the screen. The Mntr function is defined as follows:
  13539.  
  13540. FUNCTION Mntr (message, item, numItems: Integer; monitorValue: LongInt;
  13541.                mDialog: DialogPtr; theEvent: EventRecord;
  13542.                screenNum: Integer; VAR screens: ScrnRsrcHandle;
  13543.                VAR scrnChanged: Boolean) : LongInt;
  13544.  
  13545. Parameters
  13546.  
  13547. message
  13548. A message number, from the list defined in the following section “Messages,”
  13549. that  the Mntr function can use to determine what action to take.
  13550.  
  13551. item
  13552. When the message parameter equals StartupMsg, indicates whether the user is a
  13553. superuser; that is, whether the user can be assumed to be very knowledgeable. If
  13554. the user is a superuser, the item parameter is 1, if not, it is 0. 
  13555.  
  13556. For other values of the message parameter, the item parameter is the dialog item
  13557. list number of the item on which the user clicked. To calculate the number in
  13558. your 'DITL' resource, subtract the number passed in the numItems parameter from
  13559. the number in the item parameter.
  13560.  
  13561. numItems
  13562. The dialog-item-list number of the last item in the Monitors control panel.
  13563.  
  13564. monitorValue
  13565. The result returned by the Mntr function the last time it was called. Because
  13566. control panel routines cannot have global variables, you might want to use the
  13567. function result to return a handle to the storage of your local data. This
  13568. handle is then available in the monitorValue parameter the next time the Mntr
  13569. function is called. The first time the function is called, monitorValue is 0.
  13570.  
  13571. mDialog
  13572. The dialog pointer for the Options dialog box. Dialog pointers are described in
  13573. the Dialog Manager chapter of Volume I.
  13574.  
  13575. theEvent
  13576. The event record for an event that caused a hitMsg, nulMsg, or keyEvtMsg
  13577. message. See the Toolbox Event Manager chapter of this volume for a discussion
  13578. of event records.
  13579.  
  13580. screenNum
  13581. The number of the screen device (that is, the monitor) that the user has
  13582. selected. Monitors are numbered consecutively, in the same order as the slots in
  13583. which the cards are installed, starting with 1.
  13584.  
  13585. screens
  13586. A handle to the 'scrn' resource. The 'scrn' resource is described in the
  13587. Graphics Devices chapter of Volume V.
  13588.  
  13589. scrnChanged
  13590. A Boolean value that you can use to indicate whether you have modified the
  13591. 'scrn' resource. Set this parameter to TRUE if you have modified the 'scrn'
  13592. resource. When ScrnChanged is TRUE, the Monitors control panel checks the 'scrn'
  13593. resource to make sure that the values in it are still valid; if there is a
  13594. problem, the Monitors control panel tries to correct it. 
  13595.  
  13596. This parameter is designed to make it easier for developers to implement a
  13597. control that changes the apparent area displayed on the screen. For example,
  13598. your monitor might be able to display either two pages of a document or a
  13599. magnified view of a single page. If the user changes the area displayed on one
  13600. screen in a system with multiple screens, the displays on adjacent screens could
  13601. overlap or show gaps. When you change the 'scrn' resource to implement this
  13602. change, the coordinates of the global rectangles for adjacent screens are no
  13603. longer contiguous. In this case, if you have set the ScrnChanged parameter to
  13604. TRUE, the Monitors control panel shifts the virtual locations of the screens to
  13605. eliminate the gaps or overlaps.
  13606.  
  13607. The result returned by the Mntr function can be either an error code or a value
  13608. that you want to have available the next time the Monitors extension is called.
  13609. Each time the extension is called, the monitorValue parameter contains the value
  13610. that the Mntr function returned the last time it was called. See also
  13611. “Error-Handling by the Mntr Function” later in this chapter.
  13612.  
  13613. _______________________________________________________________________________
  13614.  
  13615. æKY Messages…to…the…Mntr…Function
  13616. æC »Messages to the Mntr Function                                           Control Panels
  13617. _______________________________________________________________________________
  13618.  
  13619. The message passed as a parameter to the Mntr function can have any of the
  13620. following values:
  13621.  
  13622. CONST
  13623. initMsg        = 1;   {initialization}
  13624. okMsg          = 2;   {user clicked on OK button}
  13625. cancelMsg      = 3;   {user clicked on CANCEL button}
  13626. hitMsg         = 4;   {user clicked on control in Options dialog}
  13627. nulMsg         = 5;   {periodic event}
  13628. updateMsg      = 6;   {update event}
  13629. activateMsg    = 7;   {not used}
  13630. deactivateMsg  = 8;   {not used}
  13631. keyEvtMsg      = 9;   {keyboard event}
  13632. superMsg       = 10;  {show superuser controls}
  13633. normalMsg      = 11;  {show only normal controls}
  13634. startupMsg     = 12;  {code has been loaded}
  13635.  
  13636. Messages
  13637.  
  13638. initMsg
  13639. Sent before the Options dialog box is displayed, when the Monitors control panel
  13640. is first called. When you receive this message you should execute initialization
  13641. code. You can use initialization code to set default values for controls and
  13642. allocate memory for local storage, for example.
  13643.  
  13644. If you do allocate storage, be sure to pass a handle to the storage as the
  13645. function result. The next time your extension is called, this value will be
  13646. available in the monitorValue parameter.
  13647.  
  13648. okMsg
  13649. The user has clicked the OK button. The OK button is a standard control put up
  13650. by the Monitors control panel. You should not make any changes irreversible
  13651. until this message is received. 
  13652.  
  13653. cancelMsg
  13654. The user has clicked the Cancel button. The Cancel button is a standard control
  13655. put up by the Monitors control panel. Return the system to the condition it was
  13656. in before the user clicked the Options button, and terminate the Mntr function.
  13657.  
  13658. hitMsg
  13659. The user has clicked an enabled control in the Options dialog box. The
  13660. dialog-item-list number of the control is passed in the Item parameter to the
  13661. Mntr function; see the preceding section for a discussion of this parameter.
  13662.  
  13663. nulMsg
  13664. Sent periodically to allow you to perform tasks that have to be done repeatedly,
  13665. such as blinking an insertion point. Do not assume any particular timing for
  13666. this message.
  13667.  
  13668. updateMsg
  13669. Sent on every update event.
  13670.  
  13671. activateMsg
  13672. Because the Options dialog box is modal, this message is not used.
  13673.  
  13674. deactivateMsg
  13675. Because the Options dialog box is modal, this message is not used.
  13676.  
  13677. keyEvtMsg
  13678. Sent on every keyboard event.
  13679.  
  13680. superMsg
  13681. The user is a superuser; that is, the user can be assumed to be very
  13682. knowledgeable. This message is sent when the user holds down the Option key
  13683. while clicking on the Options button, and could be sent by other mechanisms in
  13684. the future. You should display any controls that you have reserved for such
  13685. users. 
  13686.  
  13687. normalMsg
  13688. Do not display controls reserved for knowledgeable users.
  13689.  
  13690. startupMsg
  13691. Sent as soon as the code in your 'mntr' resource has been loaded, before the
  13692. Monitors control panel finds any resources referred to by your Mntr function.
  13693. You can then load and modify any resources that must allow for the capabilities
  13694. of the system or for whether the user is a superuser. You can call the Gestalt
  13695. function to determine the capabilities of the system and you can check the value
  13696. of the item parameter in the Mntr function call to determine whether the user is
  13697. a superuser. You can use this message, for example, to modify your 'DITL'
  13698. resource to display special controls for superusers.
  13699.  
  13700. _______________________________________________________________________________
  13701.  
  13702. æKY Error-Handling…by…the…Mntr…Function
  13703. æC »Error-Handling by the Mntr Function                                     Control Panels
  13704. _______________________________________________________________________________
  13705.  
  13706. If an error occurs, your Mntr function should display an error dialog box and
  13707. then return a value between 1 and 255. If your code returns a value in this
  13708. range, the Monitors control panel closes the Options dialog box immediately and
  13709. no more calls are made to your code. If your code returns an error in response
  13710. to the InitMsg message, the Monitors control panel does not display the Options
  13711. dialog box. You can display an alert describing the error before returning
  13712. control to the Monitors control panel.
  13713.  
  13714. _______________________________________________________________________________
  13715.  
  13716. æKY 'DITL'…Resource
  13717. æC »'DITL' Resource                                                         Control Panels
  13718. _______________________________________________________________________________
  13719.  
  13720. The 'DITL' resource is a standard dialog item list, as described in the Dialog
  13721. Manager chapters of Volumes I and V. For an example of this resource, see 
  13722. “Sample of a File That Extends the Monitors Control Panel,” later in this
  13723. chapter.
  13724.  
  13725. _______________________________________________________________________________
  13726.  
  13727. æKY 'RECT'…Resource
  13728. æC »'RECT' Resource                                                         Control Panels
  13729. _______________________________________________________________________________
  13730.  
  13731. The 'RECT' resource describes the size and shape of the area taken up by your
  13732. controls. Assume that the origin (that is, the top left corner) of the local
  13733. coordinate system for your dialog items is at (0,0). (In this coordinate system,
  13734. the Options dialog items put on the screen by the Monitors control panel would
  13735. have a right edge at 319 and a negative top coordinate.)  The Monitors control
  13736. panel places your controls so that they start immediately below the standard
  13737. Options controls (see Figure 9-2).
  13738.  
  13739. Because the Monitors control panel transforms the coordinates of your controls
  13740. to the coordinate system used by the Options dialog box, you must use the
  13741. GetDItem procedure (described in the Dialog Manager chapter of Volume I) to get
  13742. the true locations of your dialog items.
  13743.  
  13744. If you want your controls to appear to be extensions of the standard controls
  13745. put up by the Monitors control panel, start them immediately below the standard
  13746. controls. If you want to separate your controls from the standard controls, draw
  13747. a line across the screen below the standard controls. You can draw the line by
  13748. making it a separate dialog item of type userItem. The procedure for the dialog
  13749. item should consist of a FrameRect procedure that draws a one-pixel-high
  13750. rectangle with coordinates of (2,1,3,319). Notice that these coordinates are
  13751. relative to the standard controls displayed by the Monitors control panel; the
  13752. control panel always places your controls below the standard controls. Dialog
  13753. items are discussed in the Dialog Manager chapter of Volume I, and the FrameRect
  13754. procedure is described in the QuickDraw chapter of Volume I.
  13755.  
  13756. Figures 9-3 and 9-4 illustrate these two styles of Options dialog boxes. Figure
  13757. 9-3 shows an Options dialog box to which the Monitors extension file has added
  13758. buttons directly beneath the Cancel button in the standard dialog box. Figure 
  13759. 9-4 shows an Options dialog box to which the Monitors extension file has added
  13760. buttons beneath a line separating the extended controls from the standard
  13761. controls.
  13762.  
  13763. ø 9.3  Monitors Option Dialog Box With Added Controls as Extensions of Standard
  13764. Controls
  13765.  
  13766. ø 9.4  Monitors Option Dialog Box With Added Controls Separate From Standard
  13767. Controls
  13768.  
  13769. _______________________________________________________________________________
  13770.  
  13771. æKY 'ICON'…and…'cicn'…Resources
  13772. æC »'ICON' and 'cicn' Resources                                             Control Panels
  13773. _______________________________________________________________________________
  13774.  
  13775. The 'ICON' resource, described in the Resource Manager chapter of this volume,
  13776. defines a black-and-white icon. The 'cicn' resource, described in the Color
  13777. QuickDraw chapter of Volume V, defines a color icon. If you include either of
  13778. these resources in the Monitors extension file, the icon is displayed in the
  13779. Options dialog box of the Monitors control panel (Figure 9-2).
  13780.  
  13781. _______________________________________________________________________________
  13782.  
  13783. æKY 'STR#'…Resource
  13784. æC »'STR#' Resource                                                         Control Panels
  13785. _______________________________________________________________________________
  13786.  
  13787. If the name for the video card that you want to display in the Options dialog
  13788. box is different from the name in the declaration ROM of the video card, you can
  13789. include a 'STR#' resource. This resource must contain pairs of Pascal strings.
  13790. The first string in each pair must be identical to the name of a video card as
  13791. returned by the Slot Manager’s SReadDrvrName function (minus the period that the
  13792. Slot Manager prefixes to the name). The second string in each pair is the name
  13793. that you want  to display in the Options dialog box. You can have as many pairs
  13794. of names in one 'STR#' resource as you wish; the Monitors control panel uses the
  13795. first match it finds.
  13796.  
  13797. _______________________________________________________________________________
  13798.  
  13799. æKY 'gama'…Resources
  13800. æC »'gama' Resources                                                        Control Panels
  13801. _______________________________________________________________________________
  13802.  
  13803. When the user presses the Option key while clicking on the Options button in the
  13804. Monitors control panel, a list of gamma tables is displayed, as shown in Figure
  13805. 9-2. The software driver for a video card uses a gamma table to correct for the
  13806. fact that the intensity of each color on a video display is not linearly
  13807. proportional to the intensity of the electron beam; in other words, the gamma
  13808. table helps the video driver to provide the most accurate colors possible for a
  13809. video display. Because the user might prefer a nonstandard color correction,
  13810. many developers of video cards provide more than one gamma table for a given
  13811. card. 
  13812.  
  13813. To include one or more gamma tables for a video card, include in the Monitors
  13814. extension file a resource of type 'gama' for each gamma table. The user can
  13815. select which gamma table to use with the monitor by clicking the name of that
  13816. table, or can select the default gamma table for that monitor by clicking the
  13817. box that appears above the gamma table (see Figure 9-2). The default gamma table
  13818. for a monitor is the one listed in the 'scrn' resource. Gamma tables are
  13819. discussed in the chapter on NuBus Card Driver Design in Designing Cards and
  13820. Drivers for the Macintosh Family and in the Graphics Devices chapter of Volume
  13821. V. The 'gama' resource type is defined in the Resource Manager chapter of this
  13822. volume. The 'scrn' resource is described in the Graphics Devices chapter of
  13823. Volume V.
  13824.  
  13825. _______________________________________________________________________________
  13826.  
  13827. æKY 'FREF',…'BNDL',…'ICN#',…and…Owner…Resources
  13828. æC »'FREF', 'BNDL', 'ICN#', and Owner Resources                             Control Panels
  13829. _______________________________________________________________________________
  13830.  
  13831. The 'FREF', 'BNDL', 'ICN#', and owner resources work together to give your file
  13832. a distinctive appearance on the desktop. These resource types are described in
  13833. the Resource Manager chapter of this volume, and examples of these resources are
  13834. given in the sample code at the end of this chapter.
  13835.  
  13836. _______________________________________________________________________________
  13837.  
  13838. æKY 'INIT'…Resource
  13839. æC »'INIT' Resource                                                         Control Panels
  13840. _______________________________________________________________________________
  13841.  
  13842. A file that  contains an extension to the Monitors control panel can contain an
  13843. 'INIT' resource. If this file is located in the INIT folder the system executes
  13844. the 'INIT' resource when the machine is switched on or reset. 'INIT' resources
  13845. are discussed in the System Resource chapter of Volume IV and in the Start
  13846. Manager chapter of Volume V. The 'INIT' resource acts independently of other
  13847. resources in the file; it need not be related to the Monitors extension in any
  13848. way.
  13849.  
  13850. _______________________________________________________________________________
  13851.  
  13852. æKY Sample…of…a…File…That…Extends…the…Monitors…Control…Panel
  13853. æC »Sample of a File That Extends the Monitors Control Panel                Control Panels
  13854. _______________________________________________________________________________
  13855.  
  13856. Listing 9-1 shows the components of a file that extends the Monitors Control
  13857. Panel.
  13858.  
  13859. Listing 9-1.  Sample of a File That Extends the Monitors Control Panel
  13860.  
  13861. Pascal source code:
  13862.  
  13863. UNIT MonExtendCDEV;
  13864.  
  13865. INTERFACE
  13866.  
  13867. USES
  13868.  
  13869.   MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf;
  13870.  
  13871. CONST
  13872.  
  13873.   textItm    = 1;   {first editTExt item in cdev}
  13874.  
  13875.   SlotCount  =  6; 
  13876.   INITMSG     = 1;  {sent before the dialog is actually displayed}
  13877.   OKMSG       = 2;  {indicates we are quitting and actions should stick}
  13878.   CANCELMSG   = 3;  {indicates we are quitting and actions should not stick}
  13879.   HITMSG      = 4;  {sent when an extensions control is hit}
  13880.   NULMSG      = 5;  {a periodic event}
  13881.   UPDATEMSG   = 6;  {this SHOULD be handled by user code and built-in controls}
  13882.   ACTIVATEMSG = 7;  {currently not used as we are a modalDialog}
  13883.   DEACTIVATEMSG = 8;{currently not used as we are a modalDialog}
  13884.   KEYEVTMSG   = 9;  {sent for keyboard events. }
  13885.                     { TextEdit should handle automatically}
  13886.   SUPERMSG    = 10; {sent if should show Super User controls}
  13887.   NORMALMSG   = 11; {sent if should not show Super User controls}
  13888.   STARTUPMSG  = 12; {sent as soon as the code is loaded, }
  13889.                     { before any resources are found}
  13890. TYPE
  13891. ScrnRecord = RECORD  {‘scrn’ info for each screen}
  13892.   srDrvrHW:       INTEGER;  {spDrvrHW from slot decl mgr’s device type}
  13893.   srSlot:         INTEGER;  {Slot number for the screen’s video card}
  13894.   srDCtlDevBase:  LONGINT;  {Base address of card’s memory}
  13895.   srMode:         INTEGER;  {sRsrcID for desired mode}
  13896.   srFlagMask:     INTEGER;  {$77FE}
  13897.   srFlags:        INTEGER;  {active, main screen, B/W or color}
  13898.   srColorTable:   INTEGER;  {Resource ID of desired ‘clut’}
  13899.   srGammaTable:   INTEGER;  {Resource ID of desired ‘gama’}
  13900.   srRect:         Rect;  {Device’s rectangle, global coordinates}
  13901.   srCtlCount:     INTEGER;  {Number of control calls}
  13902. END;
  13903.  
  13904. ScrnRecordPtr = ^ScrnRecord;
  13905. ScrnRecordHandle = ^ScrnRecordPtr;
  13906.  
  13907. ScrnRsrc = RECORD    {Complete ‘scrn’ resource}
  13908.   count:     INTEGER;  {Number of screens configured here}
  13909.   scrnRecs:  ARRAY[1..SlotCount] OF ScrnRecord;  {Config for @ one}
  13910. END;
  13911.  
  13912. ScrnRsrcPtr = ^ScrnRsrc;
  13913. ScrnRsrcHandle = ^ScrnRsrcPtr;
  13914. CodePtr = ^LONGINT;    {Dummy pointer type}
  13915.  
  13916. FUNCTION MonExtend (message,    {the action to handle}
  13917.     Item,        {the DITL item hit or 0}
  13918.     numItems:  INTEGER;  {the number of Monitors last item}
  13919.     monitorValue:LONGINT;  {value returned last time. Defaults to 0}
  13920.     mDialog:  DialogPtr;  {the dialog pointer}
  13921.     theEvent:  EventRecord;{event that caused the message to happen}
  13922.     ScreenNum:  INTEGER;  {the number of the screen to affect}
  13923.     VAR Screens:ScrnRsrcHandle;  {the screen resource to change if desired}
  13924.     VAR ScrnChanged:  BOOLEAN  {TRUE if Monitors should clean up screens}
  13925.     ):LONGINT;  {value to pass back as monitorValue }
  13926.               { or an error code}
  13927.  
  13928.  
  13929. IMPLEMENTATION
  13930.  
  13931. FUNCTION MonExtend (  message,Item,numItems:  INTEGER;
  13932.             monitorValue:  LONGINT;
  13933.             mDialog:  DialogPtr;
  13934.             theEvent:  EventRecord;
  13935.             ScreenNum:  INTEGER;
  13936.             VAR Screens:  ScrnRsrcHandle;
  13937.             VAR ScrnChanged: BOOLEAN
  13938.           ):LONGINT;  
  13939.  
  13940. VAR
  13941.   tempChar  : CHAR;
  13942. BEGIN
  13943.   CASE message OF
  13944.   initMSG:        {initialize cdev}
  13945.     BEGIN
  13946.       {do nothing at all}
  13947.     END;
  13948.   END;
  13949.   MonExtend := monitorValue;  { return old value}
  13950. END; {MonExtend}
  13951. END.
  13952.  
  13953. Rez source code:
  13954.  
  13955. #include "Types.r"
  13956. #include "SysTypes.r"
  13957.  
  13958. type 'kcah' as 'STR ';
  13959.  
  13960. type 'card' as 'STR ';
  13961.  
  13962. type 'sysz' { unsigned hex longint; };
  13963.  
  13964. type 'RECT' 
  13965. {
  13966.   rect;
  13967. };
  13968.  
  13969. type 'vers' {
  13970.     hex byte;    /* Major revision in BCD*/
  13971.     hex byte;    /* Minor vevision in BCD*/
  13972.     hex byte  development = 0x20,  /* Release stage*/
  13973.     alpha = 0x40,
  13974.     beta = 0x60,
  13975.     final = 0x80, /* or */ release = 0x80;
  13976.     hex byte;    /* Non-final release #  */
  13977.     integer  Country;  /* Country code*/
  13978.     pstring;    /* Short version number  */
  13979.     pstring;    /* Long version number  */
  13980. };
  13981.  
  13982. resource 'sysz' (0, purgeable) {
  13983.   $1000    /* about 64k needed in system heap, for a test */
  13984. };
  13985.  
  13986.  
  13987. resource 'vers' (1) {
  13988.   0x01, 0x00, release, 0x00,
  13989.   verUS,
  13990.   "0.00",
  13991.   "0.00, Copyright © 1989 Apple Computer, Inc."
  13992. };
  13993.  
  13994. resource 'kcah' (0, purgeable) {
  13995.   "Monitors Extension Sample by Macintosh Developer Technical Support"
  13996. };
  13997.  
  13998. resource 'BNDL' (128, purgeable) {
  13999.   'kcah',
  14000.   0,
  14001.   {
  14002.   'ICN#', {0, 128},
  14003.   'FREF', {0, 128}
  14004.   }
  14005. };
  14006.  
  14007.  
  14008. resource 'ICN#' (128, purgeable) {
  14009.   {  /* array: 2 elements */
  14010.     /* [1] */
  14011.     $"0000 0000 07FF FFE0 0800 0010 09FF FF90"
  14012.     $"0A00 0050 0A00 0050 0AF3 E750 0A88 8850"
  14013.     $"0A88 8850 0A88 8650 0A88 8150 0A88 8150"
  14014.     $"0AF0 8E50 0A00 0050 0A00 0050 0A00 0050"
  14015.     $"09FF FF90 0800 0010 0FFF FFF0 0800 0010"
  14016.     $"0800 0010 0800 0010 0800 7F10 0800 0010"
  14017.     $"0800 0010 0800 0010 0800 0010 07FF FFE0"
  14018.     $"0400 0020 0400 0020 0400 0020 07FF FFE0",
  14019.     /* [2] */
  14020.     $"0000 0000 07FF FFE0 0FFF FFF0 0FFF FFF0"
  14021.     $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
  14022.     $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
  14023.     $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
  14024.     $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
  14025.     $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
  14026.     $"0FFF FFF0 0FFF FFF0 0FFF FFF0 07FF FFE0"
  14027.     $"07FF FFE0 07FF FFE0 07FF FFE0 07FF FFE0"
  14028.   }
  14029. };
  14030.  
  14031. data 'ICON' (-4096, purgeable) {
  14032.   $"0000 0000 07FF FFE0 0800 0010 09FF FF90"        
  14033.   $"0A00 0050 0A00 0050 0AF3 E750 0A88 8850"        
  14034.   $"0A88 8850 0A88 8650 0A88 8150 0A88 8150"        
  14035.   $"0AF0 8E50 0A00 0050 0A00 0050 0A00 0050"        
  14036.   $"09FF FF90 0800 0010 0FFF FFF0 0800 0010"       
  14037.   $"0800 0010 0800 0010 0800 7F10 0800 0010"        
  14038.   $"0800 0010 0800 0010 0800 0010 07FF FFE0"        
  14039.   $"0400 0020 0400 0020 0400 0020 07FF FFE0"      
  14040.   $"0000 0000 07FF FFE0 0FFF FFF0 0FFF FFF0"       
  14041.   $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"     
  14042.   $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"      
  14043.   $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"       
  14044.   $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"      
  14045.   $"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"       
  14046.   $"0FFF FFF0 0FFF FFF0 0FFF FFF0 07FF FFE0"     
  14047.   $"07FF FFE0 07FF FFE0 07FF FFE0 07FF FFE0"      
  14048. };
  14049.  
  14050. resource 'DITL' (-4096, purgeable) {
  14051.   {  /* array DITLarray: 1 element  */
  14052.     /* [1] */
  14053.     {15, 110, 50, 280},
  14054.     StaticText {
  14055.       disabled,
  14056.       "Macintosh Developer Technical Support Mo"
  14057.       "nitor Extension Example © 1989"
  14058.     }
  14059.   }
  14060. };
  14061.  
  14062. resource 'FREF' (128, purgeable) {
  14063.   'cdev',
  14064.   0,
  14065.   ""
  14066. };
  14067.  
  14068.  
  14069.  
  14070.  
  14071. resource 'RECT' (-4096, purgeable)
  14072. {
  14073.   {-50,0,0,320}
  14074. };
  14075.  
  14076. resource 'card' (-4096, purgeable)
  14077. {
  14078.   "Toby frame buffer card"
  14079. };
  14080. _______________________________________________________________________________
  14081.  
  14082. æKY Including…Another…Control…Panel…Definition…in…a…Monitors…Extension
  14083. æC »Including Another Control Panel Definition in a Monitors Extension      Control Panels
  14084. _______________________________________________________________________________
  14085.  
  14086. A control panel file that contains an extension to the Monitors control panel
  14087. can also contain a definition for another, separate control panel. You might
  14088. want to include both an extension to the Monitors control panel and a new
  14089. control panel definition in the same file, for example, if each controlled some
  14090. features of the same video card. Any control panel definition must include a 
  14091. 'cdev' resource and the other resources described in the Control Panel chapter
  14092. of Volume V. 
  14093.  
  14094. Because the control panel resources and the Monitors extension resources in the
  14095. file have different resource ID numbers, the Finder handles them separately. If
  14096. the user opens a control panel file containing both a control panel definition
  14097. and an extension to the Monitors control panel, the control panel defined in
  14098. that file appears on the screen and the Finder ignores the Monitors extension in
  14099. that file. If the user opens the Monitors control panel file, then the Monitors
  14100. cdev function searches the other control panel files in the same folder for
  14101. extensions and ignores any 'cdev' resources it finds in those files. The user
  14102. cannot open a control panel file that contains only an extension to the Monitors
  14103. control panel; such a file can be opened only by the Monitors cdev function.
  14104.  
  14105. _______________________________________________________________________________
  14106.  
  14107. æKY Summary…of…the…Extension…File…for…the…Monitors…Control…Panel
  14108. æC »SUMMARY OF THE EXTENSION FILE FOR THE MONITORS CONTROL PANEL            Control Panels
  14109. _______________________________________________________________________________
  14110.  
  14111. The following cards summarize the constants and routines for the Monitors
  14112. Control Panel.
  14113. _______________________________________________________________________________
  14114.  
  14115. æKY Control…Panels…Constants
  14116. æC »Constants                                                               Control Panels
  14117. _______________________________________________________________________________
  14118.  
  14119. CONST
  14120. INITMSG        = 1;  {initialization}
  14121. OKMSG          = 2;  {user clicked on OK button}
  14122. CANCELMSG      = 3;  {user clicked on CANCEL button}
  14123. HITMSG         = 4;  {user clicked on control in Options dialog}
  14124. NULMSG         = 5;  {periodic event}
  14125. UPDATEMSG      = 6;  {update event}
  14126. ACTIVATEMSG    = 7;  {not used}
  14127. DEACTIVATEMSG  = 8;  {not used}
  14128. KEYEVTMSG      = 9;  {keyboard event}
  14129. SUPERMSG       = 10; {show superuser controls}
  14130. NORMALMSG      = 11; {show only normal controls}
  14131. STARTUPMSG     = 12; {code has been loaded}
  14132. _______________________________________________________________________________
  14133.  
  14134. æKY Control…Panels…Routines
  14135. æC »Routines                                                                Control Panels
  14136. _______________________________________________________________________________
  14137.  
  14138. FUNCTION Mntr   (message, Item, numItems: Integer; monitorValue: LongInt; 
  14139.                  mDialog: DialogPtr; theEvent: EventRecord; ScreenNum: Integer;
  14140.                  VAR Screens: ScrnRsrcHandle; VAR ScrnChanged: BOOLEAN) :
  14141.                  LongInt;
  14142.  
  14143. _______________________________________________________________________________
  14144.  
  14145.  
  14146. æKY DatabaseAccessManager
  14147. æC 
  14148. _______________________________________________________________________________
  14149.  
  14150. DATABASE ACCESS MANAGER
  14151. _______________________________________________________________________________
  14152.  
  14153. About…the…Database…Access…Manager…Chapter
  14154. About…the…Database…Access…Manager
  14155.     The…High-Level…Interface
  14156.     Sending…a…Query…Through…the…High-Level…Interface
  14157.     Retrieving…Data…Through…the…High-Level…Interface
  14158.     The…Low-Level…Interface
  14159.     Sending…a…Query…Through…the…Low-Level…Interface
  14160.     Retrieving…Data…Through…the…Low-Level…Interface
  14161.     Comparison…of…the…High-Level…and…Low-Level…Interfaces
  14162. Database…Access…Manager…User…Interface…Guidelines
  14163.     General…Guidelines…for…Database…Access…Manager
  14164.     User…Control
  14165.     User…Feedback
  14166.     High-Level…Database…Access
  14167.     Low-Level…Database…Access
  14168.     Query…Documents
  14169. Using…the…Database…Access…Manager
  14170.     Executing…Routines…Asynchronously
  14171.     Using…the…High-Level…Interface
  14172.     Writing…a…Status…Routine…for…High-Level…Functions
  14173.     Using…the…Low-Level…Interface
  14174.     Getting…Information…About…Sessions…in…Progress
  14175.     Processing…Query…Results
  14176.     Getting…Query…Results
  14177.     Converting…Query…Results…to…Text
  14178. Creating…a…Query…Document
  14179.     Contents…of…a…Query…Document
  14180.     Query…Records…and…Query…Resources
  14181.     Query…Records
  14182.     Query…Resources
  14183.     Writing…a…Query…Definition…Function
  14184. Database…Access…Manager…Routines
  14185.     Asynchronous…Execution…of…Routines
  14186.     Initializing…and…Closing…the…Database…Access…Manager
  14187.     High-Level…Interface
  14188.     Handling…Query…Documents
  14189.     Handling…Query…Results
  14190.     Low-Level…Interface
  14191.     Controlling…the…Session
  14192.     Sending…and…Executing…Queries
  14193.     Retrieving…Results
  14194.     Installing…and…Removing…Result…Handlers
  14195. Summary…of…the…Database…Access…Manager
  14196.     Database…Access…Manager…Constants
  14197.     Database…Access…Manager…Data…Types
  14198.     Database…Access…Manager…Routines…Summary
  14199.     Database…Access…Manager…Result…Codes
  14200.     Assembly-Language…Information…for…Database…Access…Manager
  14201. _______________________________________________________________________________
  14202.  
  14203.  
  14204.  
  14205. æKY About…the…Database…Access…Manager…Chapter
  14206. æC »ABOUT THIS CHAPTER                                             Database Access Manager
  14207. _______________________________________________________________________________
  14208.  
  14209. This chapter describes how your application can use the Database Access Manager
  14210. to communicate with a database application that is running on a remote computer.
  14211. It also provides information for system programmers who want to provide an
  14212. interface between the Database Access Manager and a remote database server, and
  14213. for those who want to provide templates to be used by applications for database
  14214. transactions.
  14215.  
  14216. The Database Access Manager is available with system software version 7.0. Use
  14217. the Gestalt function described in the Compatibility Guidelines chapter of this
  14218. volume to determine whether the Database Access Manager is present.
  14219.  
  14220. The Database Access Manager allows your application to communicate with a
  14221. database even if you do not know anything about databases in general or the
  14222. specific database program that the users of your software will be using. All
  14223. your application needs is a few high-level Database Access Manager functions and
  14224. access to a file called a query document. The query document, provided by
  14225. another application, contains commands and data (the query) in the format
  14226. appropriate for the database program on the remote computer. 
  14227. The Database Access Manager also provides a low-level interface for use by
  14228. applications that are capable of creating their own queries and that therefore
  14229. do not have to use query documents. 
  14230. If your application uses only the high-level interface and relies on query
  14231. documents created by other programs, then all the routines you need to know are
  14232. described in this chapter. However, if you want to create a query document or an
  14233. application that uses the low-level interface, then you must also be familiar
  14234. with the command language used by the remote database server. 
  14235. You need the information in this chapter if you want your application to
  14236. communicate with a remote database application, if you want to write a query
  14237. document, or if you want to write a database extension, that is, code that
  14238. provides an interface between the Database Access Manager and a remote database
  14239. program. To create a database extension, you must also know how to communicate
  14240. with the remote database server.
  14241.  
  14242. Note:  Although the Database Access Manager was designed to make it easy for
  14243. your application to communicate with a database running on a remote computer,
  14244. there is no reason in principle why the database could not be local—that is,
  14245. running on the same computer as your application. To implement such a system,
  14246. you would have to have a database that runs on a Macintosh computer and that has
  14247. a command-language interface, plus a database extension that can use that
  14248. command language. In most cases, it would be much simpler to run the database as
  14249. a separate application and use the Clipboard to transfer data into and out of
  14250. the database.
  14251.  
  14252. Apple Computer, Inc. provides a database extension that uses the CL/1™
  14253. connectivity language. If you want to write an application that uses the
  14254. low-level interface to communicate with a CL/1 server, or if you want to create
  14255. a query document that uses CL/1, you must be familiar with CL/1. CL/1
  14256. Connectivity Language, available from APDA, fully describes this language.
  14257.  
  14258. The rest of this chapter provides an overview and description of the Database
  14259. Access Manager, including
  14260.  
  14261.   •   diagrams and conceptual descriptions of the components and processes
  14262.       involved in using the high-level and low-level interfaces
  14263.  
  14264.   •   descriptions, flowcharts, and program fragments that provide a
  14265.       step-by-step guide to the use of the high-level and low-level interfaces
  14266.  
  14267.   •   instructions for creating a query document
  14268.  
  14269.   •   complete descriptions of all Database Access Manager routines
  14270. _______________________________________________________________________________
  14271.  
  14272. æKY About…the…Database…Access…Manager
  14273. æC »ABOUT THE DATABASE ACCESS MANAGER                              Database Access Manager
  14274. _______________________________________________________________________________
  14275.  
  14276. The Database Access Manager provides a standard interface that enables Macintosh
  14277. applications to communicate with any number of databases through a variety of
  14278. database servers. A database server is the application on the remote computer
  14279. that acts as an interface between the database management software on the
  14280. Macintosh® computer and the database software on the remote computer. 
  14281. The Database Access Manager has two application interfaces: the high-level
  14282. interface and the low-level interface. If the proper database extension and
  14283. query documents are available in the user’s system, you can use the high-level
  14284. interface to communicate with a database without having any knowledge of the
  14285. command language that the database server uses. Even if you use the low-level
  14286. interface, your application can isolate the user from any specific knowledge of
  14287. the database or the database server’s command language.
  14288.  
  14289. This section presents an overview and description of the Database Access
  14290. Manager, including diagrams and conceptual descriptions of the components and
  14291. processes involved in using the high-level and low-level interfaces. Next,
  14292. “Using the Database Access Manager” includes descriptions, flow charts, and
  14293. program fragments that provide a step-by-step guide to the use of the high-level
  14294. and low-level interfaces. The section “Creating a Query Document” describes the
  14295. contents and function of a query document. You do not have to read this section
  14296. unless you are writing an application that creates query documents, although if
  14297. you are using the high-level interface you might be interested to know just how
  14298. a query document works.      
  14299. Figure 7-1 illustrates database communication. The arrows in Figure 7-1 show the
  14300. flow of information, not the paths of commands or control signals. See Figures 
  14301. 7-2 and 7-3 for the sequences involved in sending and retrieving data.
  14302.  
  14303. ø 7.1  The database communication system
  14304.  
  14305. _______________________________________________________________________________
  14306.  
  14307. æKY The…High-Level…Interface
  14308. æC »The High-Level Interface                                       Database Access Manager
  14309. _______________________________________________________________________________
  14310.  
  14311. As Figure 7-1 shows, a database-naive application—that is, one that cannot
  14312. prepare a query for a specific database server—uses the Database Access 
  14313. Manager’s high-level routines to communicate with a remote database server.
  14314. Because the application cannot prepare a query, it must use a query document to
  14315. provide one. A query document can contain code, called a query definition
  14316. function, that prompts the user for information and modifies the query before
  14317. the Database Access Manager sends it to the remote database server. The exact
  14318. format of a query definition function is described in the section “Writing a
  14319. Query Definition Function” later in this chapter.
  14320.  
  14321. Note:  The term query refers to any string of commands that can be executed by a
  14322. database server. A query can send data to a database, retrieve data from a
  14323. database, or reorganize the data in a database. The Database Access Manager does
  14324. not interpret or execute the query; it only implements the interface (sometimes
  14325. called the application program interface, or API) that allows you to send the
  14326. query to the database server. 
  14327. When you want to use the high-level routines to execute a query on a remote
  14328. database server, you first select a query document or allow the user to select
  14329. one. You use high-level routines to 
  14330.  
  14331.   •   open the query document 
  14332.  
  14333.   •   execute the query definition function to modify the query
  14334.  
  14335.   •   send the query to the remote database server
  14336.  
  14337.   •   retrieve the results from any query that asks for information from the
  14338.       database.
  14339.  
  14340.   •   convert to text the results returned by a query
  14341.  
  14342. For example, suppose Mom’s Rubber Duck Company has a database on a minicomputer
  14343. that contains a mailing list of all of its customers. The database has a CL/1
  14344. interface and Mom’s marketing manager has a Macintosh computer with an
  14345. application that uses high-level Database Access Manager routines to communicate
  14346. with the remote database server. As Figure 7-2 illustrates, the marketing
  14347. manager must also have a query document, created by another application, that
  14348. she can use to send a new address to the mailing list on the remote
  14349. minicomputer. The query document can be as complex or as simple as its creator
  14350. cares to make it; in this example, the query document is designed specifically
  14351. to change addresses in the rubber duck mailing list. The marketing manager might
  14352. have several other query documents available as well; one to add new entries to
  14353. the mailing list, one to extract a mailing list for a specific zip code, one to
  14354. list all of the customers who have made a purchase within the last year, and so
  14355. on.
  14356.  
  14357. ø 7.2  Using high-level Database Access Manager routines to send a query to a
  14358. database and retrieve data
  14359. _______________________________________________________________________________
  14360.  
  14361. æKY Sending…a…Query…Through…the…High-Level…Interface
  14362. æC »Sending a Query Through the High-Level Interface               Database Access Manager
  14363. _______________________________________________________________________________
  14364.  
  14365. To update the mailing list with a new address for customer Marvin Moody, the
  14366. marketing manager chooses the Open Query menu item from the File menu in her
  14367. application. From the list of query documents displayed, she chooses one named
  14368. New Address. 
  14369.  
  14370. The application calls the Database Access Manager function DBGetNewQuery. This
  14371. function opens the New Address query document and creates a partial query from
  14372. the information in the query document. The partial query specifies the type of
  14373. data (a character string), the column into which the data item should go (the
  14374. address column), and the row to be modified (the Marvin Moody row). The partial
  14375. query lacks the actual data (the new address) that the marketing manager wants
  14376. to send to the database. 
  14377.  
  14378. Next, the application calls the DBStartQuery function, which in turn calls the
  14379. query definition function in the query document. The query definition function
  14380. displays a dialog box that asks for the name of the person and the new address.
  14381. When the marketing manager types in the requested information and clicks OK, the
  14382. query definition function adds the data to the partial query in memory. The
  14383. query is now complete. 
  14384.  
  14385. Next, the DBStartQuery function sends the query to the CL/1 database extension,
  14386. and the database extension sends the query over a communications net to the
  14387. remote CL/1 server. Finally, the DBStartQuery function commands the CL/1 server
  14388. to execute the query. 
  14389. _______________________________________________________________________________
  14390.  
  14391. æKY Retrieving…Data…Through…the…High-Level…Interface
  14392. æC »Retrieving Data Through the High-Level Interface               Database Access Manager
  14393. _______________________________________________________________________________
  14394.  
  14395. When an application wants to retrieve data that it requested from a database,
  14396. the application calls the DBGetQueryResults function. This function determines
  14397. when the data is available, retrieves it from the database server, and places
  14398. the data in a record in memory. The application can then call the
  14399. DBResultsToText function, which uses routines called result handlers to convert
  14400. each data item to a character string. The DBResultsToText function passes to the
  14401. application a handle to the converted data. Data items and result handlers are
  14402. described in “Processing Query Results” later in this chapter.
  14403.  
  14404. _______________________________________________________________________________
  14405.  
  14406. æKY The…Low-Level…Interface
  14407. æC »The Low-Level Interface                                        Database Access Manager
  14408. _______________________________________________________________________________
  14409.  
  14410. A database-aware application communicates through the low-level interface of the
  14411. Database Access Manager. You can use the low-level interface to
  14412.  
  14413.   •   establish communication with the remote database server, sending the user
  14414.       name, password, and other information to the database server
  14415.  
  14416.   •   send a query to the database server
  14417.  
  14418.   •   execute the query that you have sent to the database server
  14419.  
  14420.   •   halt execution of the query
  14421.  
  14422.   •   return status and errors from the remote database server
  14423.  
  14424.   •   send data to the database
  14425.  
  14426.   •   retrieve data from the database
  14427.  
  14428. For example, suppose Mom’s Rubber Duck Company has a database on a minicomputer
  14429. that contains a mailing list of all of its customers. The database has a CL/1
  14430. interface and Mom’s marketing manager has a Macintosh computer with an
  14431. application that uses low-level Database Access Manager routines to communicate
  14432. with the remote database server. Figure 7-3 illustrates the use of the low-level
  14433. interface. Notice that if you use the high-level interface (Figure 7-2), the
  14434. query document and the Database Access Manager prepare the query, send the
  14435. query, retrieve the query results, and translate the data for you. If you use
  14436. the low-level interface, on the other hand, you must perform these functions
  14437. yourself.
  14438.  
  14439. ø 7.3  Using low-level Database Access Manager routines to send a query to a
  14440. database and retrieve data
  14441. _______________________________________________________________________________
  14442.  
  14443. æKY Sending…a…Query…Through…the…Low-Level…Interface
  14444. æC »Sending a Query Through the Low-Level Interface                Database Access Manager
  14445. _______________________________________________________________________________
  14446.  
  14447. To update the mailing list with a new address for customer Marvin Moody, the
  14448. marketing manager enters the new address into her application. The application
  14449. prepares a CL/1 statement (a query) that specifies the type of data (a character
  14450. string), the column into which the data item should go (the address column), the
  14451. row to be modified (the Marvin Moody row), plus the actual data the application
  14452. wishes to send (Marvin Moody’s address). The application then passes this query
  14453. to the Database Access Manager using the low-level interface. (The application
  14454. can send the query in several pieces, or all at once). The Database Access
  14455. Manager sends the query to the CL/1 database extension in the Macintosh, and the
  14456. database extension sends the query to the remote CL/1 server. 
  14457. _______________________________________________________________________________
  14458.  
  14459. æKY Retrieving…Data…Through…the…Low-Level…Interface
  14460. æC »Retrieving Data Through the Low-Level Interface                Database Access Manager
  14461. _______________________________________________________________________________
  14462.  
  14463. Once the query begins executing, the application can periodically check with the
  14464. remote database server to determine whether the data is ready (Figure 7-3). When
  14465. the data is available, the application must retrieve it one data item at a time.
  14466. An application that uses the low-level interface must determine the data type of
  14467. each data item, convert the data into a format that is meaningful to the user,
  14468. and store the data in memory allocated by the application. Data types are
  14469. described in “Processing Query Results” later in this chapter.
  14470.  
  14471. Note that neither the Database Access Manager nor the database extension reads,
  14472. modifies, or acts on the query that an application sends to the remote database
  14473. server. The database server does execute the query, causing the database to
  14474. accept new data or prepare data for the application. To use the low-level
  14475. interface to communicate with a remote database server, your application must be
  14476. capable of preparing a query that can be executed by the database server.
  14477.  
  14478. _______________________________________________________________________________
  14479.  
  14480. æKY Comparison…of…the…High-Level…and…Low-Level…Interfaces
  14481. æC »Comparison of the High-Level and Low-Level Interfaces          Database Access Manager
  14482. _______________________________________________________________________________
  14483.  
  14484. An application that uses the low-level interface to send a query to the database
  14485. server must prepare the query, initiate communication with the database server,
  14486. send the query to the database server, and execute the query. Each step in this
  14487. process requires calling one or more low-level routines. 
  14488.  
  14489. The low-level application interface uses functions that are very similar to the
  14490. CL/1 application program interface (API) routines. In addition, there is a
  14491. one-to-one correspondence between the low-level routines and the commands sent
  14492. by the Database Access Manager to the database extension. In the case of the
  14493. CL/1 database extension, there is also a close relationship between these
  14494. routines and the commands sent by the database extension to the remote CL/1
  14495. server.
  14496.  
  14497. The high-level interface between the Database Access Manager and the
  14498. application, on the other hand, consists of only a few routines, each of which
  14499. might call several low-level routines to accomplish its tasks. For example, a
  14500. single high-level function can call the query definition function, initiate
  14501. communication with the remote database server, send the query to the remote
  14502. database server, and execute the query. 
  14503.  
  14504. Although in concept the low-level routines and high-level routines serve
  14505. separate purposes, there is nothing to prevent you from using calls to both in a
  14506. single application. For example, you might use low-level routines to send a
  14507. query to a remote database server and high-level routines to read the results
  14508. and convert them to text.
  14509.  
  14510. _______________________________________________________________________________
  14511.  
  14512. æKY Database…Access…Manager…User…Interface…Guidelines
  14513. æC »DATABASE ACCESS MANAGER USER INTERFACE GUIDELINES              Database Access Manager
  14514. _______________________________________________________________________________
  14515.  
  14516. System software version 7.0 provides the ability for applications to access
  14517. information from a wide variety of databases on remote minicomputers or
  14518. mainframe computers. This section presents interface guidelines regarding
  14519. database access. Applications can implement the Database Access Manager in three
  14520. ways. An application can  
  14521.  
  14522.   •   directly use the Toolbox routines to establish and manage a connection
  14523.       with a target database (low-level access)
  14524.  
  14525.   •   create a query document that other applications can use to communicate
  14526.       with a target database (low-level access)
  14527.  
  14528.   •   execute a query document that gains database access for the application
  14529.       (high-level access)
  14530. _______________________________________________________________________________
  14531.  
  14532. æKY General…Guidelines…for…Database…Access…Manager
  14533. æC »General Guidelines                                             Database Access Manager
  14534. _______________________________________________________________________________
  14535.  
  14536. When you develop an application that uses the Database Access Manager, you
  14537. should consider these user interface guidelines and the associated principles. 
  14538. _______________________________________________________________________________
  14539.  
  14540. æKY User…Control
  14541. æC »User Control                                                   Database Access Manager
  14542. _______________________________________________________________________________
  14543.  
  14544. When designing a database access feature or application, keep in mind that the
  14545. user should have access to the computer’s abilities as much as possible. Design
  14546. your application so that as much as possible of the database access process
  14547. happens in the background. Call the Database Access Manager asynchronously
  14548. whenever the database extension you are using supports asynchronous calls. In
  14549. particular data retrieval queries should run in the background. 
  14550.  
  14551. After issuing a query, return control of the computer to users so that they may
  14552. work on other tasks or switch to other applications while the query runs. Any
  14553. time a background task requires the user’s attention, follow the guidelines in
  14554. the User Interface Guidelines chapter to notify the user. A background task
  14555. should never take control from the user by posting an alert box in front of the
  14556. active application’s windows. Any message that you post should identify the
  14557. query that requires attention. For example a dialog box may display the message,
  14558. “The query Get Employee Information was cancelled because the connection was
  14559. unexpectedly broken.”  
  14560.  
  14561. If your application allows more than one simultaneous connections to databases,
  14562. or more than one query document to run, provide a modeless window that lists the
  14563. open connections and queries. This way the user can monitor the status of open
  14564. queries and cancel them if necessary. 
  14565.  
  14566. Allow the user to limit the amount of disk space that must remain free after any
  14567. transaction. For example, a user may wish to specify that 1 MB of space always
  14568. be free. Cancel any transaction that would exceed the user’s limit and notify
  14569. the user.  
  14570. _______________________________________________________________________________
  14571.  
  14572. æKY User…Feedback
  14573. æC »User Feedback                                                  Database Access Manager
  14574. _______________________________________________________________________________
  14575.  
  14576. Keep the user informed about status, progress, and error conditions. Inform the
  14577. user before the computer becomes modal and unavailable. Use the spinning beach
  14578. ball cursor or the animated watch cursor to indicate a call that takes several
  14579. seconds to execute. Use a dialog box to indicate any process that lasts longer
  14580. than a few seconds. For example, connecting to a remote database could take a
  14581. couple of minutes. In this case include a Cancel button in the dialog box so
  14582. that the user can cancel the operation. When possible display a progress
  14583. indicator to show how long a process lasts. Warn the user before doing anything
  14584. potentially dangerous or irreversible, such as deleting all of a user’s data
  14585. files to replace them with data retrieved from a database. Allow the user to
  14586. cancel an interaction whenever possible.   
  14587.  
  14588. When a data retrieval query terminates prematurely, retrieve the data and make
  14589. it available to the user with a warning that it is incomplete. This allows the
  14590. user to take advantage of the partial data and decide whether or not to run the
  14591. query again.  
  14592. _______________________________________________________________________________
  14593.  
  14594. æKY High-Level…Database…Access
  14595. æC »High-Level Database Access                                     Database Access Manager
  14596. _______________________________________________________________________________
  14597.  
  14598. High-level database access can be implemented by applications that want to
  14599. communicate with a remote database. In this case your application calls a query
  14600. document to do the work of communicating with the database. Applications that
  14601. implement this type of database access need to follow the general guidelines
  14602. presented previously in this section, and the guidelines described here.  
  14603. Include an Open Query menu command in the File menu. The command is equivalent
  14604. to the Open file command in meaning. When the user chooses this command, display
  14605. the standard file dialog box filtered to show only available query documents.
  14606. The user then can choose the desired query document. The query document sends
  14607. the query to the database. Depending on the type of query, the database could
  14608. receive information, send back information, report the status of the database,
  14609. or perform some other task. Upon terminating the data access session, save any
  14610. data retrieved into the query document.and then close the query document.   
  14611. Users can subscribe to the data in a query document using the Edition Manager by
  14612. subscribing to the query document. See the Edition Manager chapter for more
  14613. information.  
  14614. _______________________________________________________________________________
  14615.  
  14616. æKY Low-Level…Database…Access
  14617. æC »Low-Level Database Access                                      Database Access Manager
  14618. _______________________________________________________________________________
  14619.  
  14620. If you implement low-level database access, you are responsible for developing
  14621. and implementing the corresponding user interface. In addition to the general
  14622. guidelines presented previously, follow the guidelines described here when you
  14623. design low-level database access features. 
  14624.  
  14625. When the target database is ready to return data, you can retrieve it all and
  14626. then display it to the user. Or you could display the data as it arrives. If the
  14627. data arrives slowly, it’s best to display it one record at a time as it arrives.
  14628. This way the user can preview the data and decide if it’s the desired
  14629. information. 
  14630.  
  14631. Provide some method of progress monitoring for the user. The Database Access
  14632. Manager allows many connections to target databases to be open at one time. A
  14633. user may want to see some indication of how many open connections exist, their
  14634. status, and their progress. This is an appropriate place to provide a way for
  14635. the user to cancel a query in progress. 
  14636. _______________________________________________________________________________
  14637.  
  14638. æKY Query…Documents
  14639. æC »Query Documents                                                Database Access Manager
  14640. _______________________________________________________________________________
  14641.  
  14642. To implement high-level database access, your application executes a query
  14643. document that can use a database extension to connect to a remote database and
  14644. access and transfer information. This section describes guidelines specific to
  14645. query documents. Also consider the general guidelines presented previously. 
  14646. All query documents should behave in fundamentally the same way. They should be
  14647. self-explanatory and should never run automatically. When your application opens
  14648. a query document, it should display a dialog box with enough information about
  14649. the query so that the user can decide if it’s the right query. The dialog box
  14650. should describe the purpose of the query, what kind of data it transfers and
  14651. which direction, the type of database it accesses, and any warnings or
  14652. instructions. The dialog box can describe how the user interprets the data, such
  14653. as the name of each field in a record. Figure 7-4 shows an example of a query
  14654. document dialog box.
  14655.  
  14656. ø 7.4  Query document identification dialog box
  14657.  
  14658. This dialog box should allow the user to cancel the request for data. In
  14659. addition, it may be useful to allow the user to set parameters in text boxes,
  14660. check boxes, or radio buttons. For example, a query to a database of financial
  14661. information could provide a list of these options: a trial balance,
  14662. profit-and-loss statements, or net worth reports. Save the last set of
  14663. user-specified parameters with the query document. This way the user can review
  14664. the parameters used to generate the data. 
  14665.  
  14666. Once a query starts running, it must be able to complete its task without user
  14667. intervention. If a query must run modally (that is, it must run to completion
  14668. before returning control to the user) be sure to notify the user of its progress
  14669. and return control to the user as soon as possible. The philosophy of this
  14670. process is similar to that of receiving electronic mail. That is, inform the
  14671. user when the information arrives, but let the user decide when to read it. 
  14672. Query documents should check data before it is transmitted to a database to be
  14673. sure it’s compatible. Establish a connection with a database only after the data
  14674. is checked.  
  14675. _______________________________________________________________________________
  14676.  
  14677. æKY Using…the…Database…Access…Manager
  14678. æC »USING THE DATABASE ACCESS MANAGER                              Database Access Manager
  14679. _______________________________________________________________________________
  14680.  
  14681. There are at least three different ways in which you can use the Database Access
  14682. Manager to communicate with a database:
  14683.  
  14684.   •   You can use low-level interface routines to send queries and retrieve
  14685.       data from the database. In this case, your application must be capable of
  14686.       preparing a query in a language appropriate for the remote database
  14687.       server.
  14688.  
  14689.   •   You can use high-level interface routines to send queries and retrieve
  14690.       data from the database. In this case, you must have one or more query
  14691.       documents provided by another application.
  14692.  
  14693.   •   You can create your own query documents and use high-level interface
  14694.       routines to send queries and retrieve data from the database. In this
  14695.       case, your application must be capable of preparing a query, but it can
  14696.       use the same query repeatedly once it has been prepared.
  14697.  
  14698. This section describes how to use the high-level and low-level interfaces to the
  14699. Database Access Manager to send queries to a remote database server. This
  14700. section also describes how to call Database Access Manager functions
  14701. asynchronously; how to determine the status of the high-level functions at
  14702. various points in their execution (and cancel execution if you so desire); how
  14703. to obtain information about Database Access Manager sessions that are in
  14704. progress; and how to retrieve query results and convert them to text.  
  14705. _______________________________________________________________________________
  14706.  
  14707. æKY Executing…Routines…Asynchronously
  14708. æC »Executing Routines Asynchronously                              Database Access Manager
  14709. _______________________________________________________________________________
  14710.  
  14711. All of the Database Access Manager low-level routines and some of the high-level
  14712. routines can execute asynchronously; that is, the routine returns control to the
  14713. application before the routine has completed execution. Your application must
  14714. call the WaitNextEvent routine periodically to allow an asynchronous routine to
  14715. complete execution.
  14716.  
  14717. All Database Access Manager routines that can execute asynchronously take as a
  14718. parameter a pointer to a parameter block known as the asynchronous parameter
  14719. block. If this pointer is NIL, the function is executed synchronously; that is,
  14720. the routine does not return control to your application until execution is
  14721. complete. 
  14722.  
  14723. The database extension is responsible for implementing asynchronous execution of
  14724. Database Access Manager routines. For example, if you call the DBSend function
  14725. to send a query to a remote database server, and the database extension calls a
  14726. device driver, the database extension can return control to your application as
  14727. soon as the device driver has placed its routine in the driver I/O queue. If the
  14728. database extension you are using does not support asynchronous execution of
  14729. routines, it returns a result code of rcDBAsyncNotSupp and terminates execution
  14730. of the routine.
  14731.  
  14732. _______________________________________________________________________________
  14733.  
  14734. æKY Using…the…High-Level…Interface
  14735. æC »Using the High-Level Interface                                 Database Access Manager
  14736. _______________________________________________________________________________
  14737.  
  14738. You can use the high-level interface to open a query document, execute the query
  14739. definition function in the query document, establish communication (initiate a
  14740. session) with a remote database server, send the query to the database server,
  14741. execute the query, retrieve any data requested by the query, and convert the
  14742. retrieved data to text. Although two or three high-level routines accomplish
  14743. most of these tasks, you must call a few low-level routines as well to control a
  14744. session with a database server. 
  14745.  
  14746. Figure 7-5 is a flowchart of a typical session using the high-level interface.
  14747.  
  14748. ø 7.5  Flowchart of session using high-level interface
  14749.  
  14750. As Figure 7-5 illustrates, you must follow this procedure to use the high-level
  14751. interface:
  14752.  
  14753. 1.  Call the InitDBPack function to initialize the Database Access Manager.
  14754.  
  14755. 2.  Call the DBInit function to establish communication with the remote database
  14756. server. The DBInit function returns an identification number, called a session
  14757. ID. This session ID is unique; no other current session, for any database
  14758. extension, has the same session ID. You must specify the session ID any time you
  14759. want to send data to or retrieve data from this session.
  14760.  
  14761. The DBInit function requires as input parameters the name of the database
  14762. extension, character strings for the remote system, user name, password, and
  14763. connection string. All of these parameters depend on the user and the user’s
  14764. computer system, including the specific database extension, host computer,
  14765. database server, and database management software in use. You will not know the
  14766. user name and password when you are writing an application, and you might not
  14767. know the values of any of these parameters. Therefore, you must display a dialog
  14768. box that prompts the user for the necessary information. 
  14769.  
  14770. If you want the Database Access Manager to call the DBInit function for you, you
  14771. can skip this step. The DBStartQuery function (step 5) automatically calls the
  14772. DBInit function if a session with the database server has not already been
  14773. established.
  14774.  
  14775. Depending on the database extension you are using, the DBInit function might
  14776. return a session ID of 0 if it fails to initiate a session, or it might return a
  14777. nonzero session ID and some result code other than noErr. In the latter case,
  14778. you can pass the session ID to the DBGetErr function to determine the cause of
  14779. the error. If the DBInit function returns a nonzero session ID and a result code
  14780. other than noErr, you must call the DBEnd function before making another attempt
  14781. to open the session or closing the Database Access Manager.
  14782.  
  14783. 3.  Select the query document that you want to use and determine the resource ID
  14784. of the 'qrsc' resource in that query document. You can use any method you like
  14785. to select the query document. One possibility is to use the SFGetFile procedure
  14786. to let the user select the query document. You can then use Resource Manager
  14787. routines to determine the resource IDs of all of the 'qrsc' resources in the
  14788. document that the user selected. The SFGetFile procedure is described in the
  14789. Standard File chapter of Volume I and the Resource Manager is described in
  14790. Volume I, Chapter 5.
  14791.  
  14792. 4.  Call the DBGetNewQuery function. The DBGetNewQuery function creates in
  14793. memory a data structure called a query record from the 'qrsc' resource that you
  14794. specify. 
  14795.  
  14796. 5.  Call the DBStartQuery function specifying the handle to the query record
  14797. that you created with the DBGetNewQuery function (step 4). 
  14798.  
  14799. You should also provide the DBStartQuery function with a handle to your status
  14800. routine. A status routine is a routine that you provide that can update windows,
  14801. check the results of the low-level calls made by the DBStartQuery and
  14802. DBGetQueryResults functions, and cancel execution of these functions when you
  14803. consider it appropriate to do so. 
  14804.  
  14805. The DBStartQuery function calls the query definition function referred to by the
  14806. query record (if any). The query definition function can prompt the user for
  14807. information and modify the query record. 
  14808.  
  14809. After the query definition function has completed execution, the DBStartQuery
  14810. function calls your status routine so that you can update your windows if
  14811. necessary. The DBStartQuery function then checks to see if communications have
  14812. been established with the remote database server. If not, it calls your status
  14813. routine so that you can put up a status dialog box, and then calls the DBInit
  14814. function. The DBStartQuery function obtains the values it needs for the DBInit
  14815. function parameters from the query record. When the DBInit function completes
  14816. execution, the DBStartQuery function calls your status routine again. 
  14817.  
  14818. Once communications have been established, the DBStartQuery function calls the
  14819. DBSend function to send the query specified by the query record to the remote
  14820. database server, and, when the DBSend function has completed execution, calls
  14821. your status routine. Finally, the DBStartQuery function uses the DBExec function
  14822. to execute the query. The DBStartQuery function calls your status routine after
  14823. the DBExec function has completed execution (that is, the query has started
  14824. executing and the DBExec function has returned control to the DBStartQuery
  14825. function) and again just before the DBStartQuery function completes execution.
  14826.  
  14827. 6.  Use the DBState function to determine the status of the query. 
  14828.  
  14829. The DBState function tells you when the database server has finished executing
  14830. the query you just sent. If you have requested data, the database server stores
  14831. the data you requested but does not send it to your application until you
  14832. request it explicitly. The DBState function tells you when the data is
  14833. available. 
  14834.  
  14835. If you did not request data, skip to step 9.
  14836.  
  14837. 7.  Call the DBGetQueryResults function. This function calls the DBGetItem
  14838. function repeatedly until the remote database server has returned all of the
  14839. data available. 
  14840.  
  14841. The DBGetQueryResults function puts the returned data into a record that
  14842. contains handles to arrays that contain the data, the type of data in each
  14843. column, and the length of each data item.
  14844.  
  14845. The DBGetQueryResults function calls your status routine after it retrieves each
  14846. data item. You can use this opportunity to display the data item for the user
  14847. and to give the user the opportunity to cancel execution of the function. The
  14848. DBGetQueryResults function also calls your status routine just before completing
  14849. execution, so that you can dispose of any memory allocated by the status
  14850. routine, remove any dialog box that you displayed, and update your windows if
  14851. necessary.
  14852.  
  14853. To convert the returned data to text, go on to the next step. If you do not want
  14854. to convert the returned data to text, skip to step 9.
  14855.  
  14856. 8.  Call the DBResultsToText function. This function calls a result handler
  14857. function for each data type. The result handler converts the data to text,
  14858. places it in a buffer, and returns a handle to the buffer. Some result handlers
  14859. are provided with the Database Access Manager; you can provide as many with your
  14860. application as you wish. Result handlers are discussed in “Processing Query
  14861. Results” later in this chapter.
  14862.  
  14863. 9.  If you are finished using the query record, call the DBDisposeQuery function
  14864. to dispose of the query record and free all the memory associated with the query
  14865. record. If you want to reuse the same query, return to step 5. You should close
  14866. the query document when you are finished using it. Be sure to save any changes
  14867. to the query or query record and any data returned by the query in the query
  14868. document.
  14869.  
  14870. If you want to use a new query document, return to step 3. If you are finished
  14871. using the database, go on to step 10.
  14872.  
  14873. 10.  When you are finished using the database, you must use the DBEnd function
  14874. to terminate the session. You must call the DBEnd function after the DBInit
  14875. function has returned a nonzero session ID, even if it also returned an error.
  14876.  
  14877. 11.  When you are finished using the Database Access Manager, call the
  14878. QuitDBPack function to close the manager.
  14879.  
  14880. Listing 7-1 uses the high-level interface to open a query document and execute
  14881. the query definition function in the document. It then retrieves the data
  14882. returned by the database server and converts the data to text. 
  14883.  
  14884. Listing 7-1.  Use of the high-level interface (TO BE PROVIDED)
  14885.  
  14886. _______________________________________________________________________________
  14887.  
  14888. æKY Writing…a…Status…Routine…for…High-Level…Functions
  14889. æC »Writing a Status Routine for High-Level Functions              Database Access Manager
  14890. _______________________________________________________________________________
  14891.  
  14892. Both of the two main high-level functions, DBStartQuery and DBGetQueryResults,
  14893. call low-level functions repeatedly. After each time they call a low-level
  14894. function, these high-level functions call a routine that you provide, called a
  14895. status routine. Your status routine can check the result code returned by the
  14896. low-level function, and can cancel execution of the high-level function before
  14897. it calls the next low-level function. Your status routine can also update your
  14898. application’s windows after the DBStartQuery function has displayed a dialog
  14899. box.
  14900.  
  14901. You provide a pointer to your status routine in the statusProc parameter to the
  14902. DBStartQuery and DBGetQueryResults functions. 
  14903.  
  14904. Here is a function declaration for a status routine.
  14905.  
  14906. FUNCTION MyStatusFunc (message: Integer; result: OSErr; dataLen, dataPlaces,
  14907.                        dataFlags: Integer; dataType: DBType; dataPtr: Ptr) :
  14908.                        Boolean;
  14909.  
  14910. Your status routine should return a value of TRUE if you want the DBStartQuery
  14911. or DBGetQueryResults function to continue execution, or FALSE to cancel
  14912. execution of the function. In the latter case, the high-level function returns
  14913. the userCanceledErr result code.
  14914.  
  14915. Note:  If you call the DBStartQuery or DBGetQueryResults functions
  14916. asynchronously, you cannot depend on the A5 register containing a pointer to
  14917. your application’s global variables when the Database Access Manager calls your
  14918. status routine.
  14919.  
  14920. The message parameter tells your status routine the current status of the
  14921. high-level function that called it. The possible values for the message
  14922. parameter depend on which function called your routine. The following status
  14923. messages can be sent to your status routine by the DBStartQuery function:
  14924.  
  14925. DBStartQuery 
  14926. message        Description
  14927. kDBUpdateWind  The DBStartQuery function has just called a query definition
  14928. function. Your status routine should process any update events that your
  14929. application has received for its windows.
  14930.  
  14931. kDBAboutToInit  The DBStartQuery function is about to call the DBInit function
  14932. to initiate a session with a remote database server. Because initiating the
  14933. session might involve establishing communication over a network, and because in
  14934. some circumstances the execution of a query can tie up the user’s computer for
  14935. some length of time, you might want to display a dialog box giving the user the
  14936. option of canceling execution at this time.
  14937.  
  14938. kDBInitComplete  The DBInit function has completed execution. When the
  14939. DBStartQuery function calls your status routine with this message, the result
  14940. parameter contains the result code returned by the DBInit function. If the
  14941. DBInit function returns the noErr result code, the DBStartQuery function calls
  14942. the DBSend function next. If the DBInit function returns any other result code,
  14943. you can display a dialog box informing the user of the problem before returning
  14944. control to the DBStartQuery function. The DBStartQuery function then returns an
  14945. error code and completes execution.
  14946.  
  14947. kDBSendComplete  The DBSend function has completed execution. When the
  14948. DBStartQuery function calls your status routine with this message, the result
  14949. parameter contains the result code returned by the DBSend function. If the
  14950. DBSend function returns the noErr result code, the DBStartQuery function calls
  14951. the DBExec function next. If the DBSend function returns any other result code
  14952. you can display a dialog box informing the user of the problem before returning
  14953. control to the DBStartQuery function. The DBStartQuery function then returns an
  14954. error code and completes execution.
  14955.  
  14956. kDBExecComplete  The DBExec function has completed execution. When the
  14957. DBStartQuery function calls your status routine with this message, the result
  14958. parameter contains the result code returned by the DBExec function. If the
  14959. DBExec function returns the noErr result code, the DBStartQuery function returns
  14960. control to your application next. If the DBExec function returns any other
  14961. result code you can display a dialog box informing the user of the problem
  14962. before returning control to the DBStartQuery function. The DBStartQuery function
  14963. then returns an error code and completes execution.
  14964.  
  14965. kDBStartQueryComplete  The DBStartQuery function has completed execution and is
  14966. about to return control to your application. The function result is in the
  14967. result parameter passed to your status routine. Your status routine can use this
  14968. opportunity to peform any final tasks, such as  disposing of memory that it
  14969. allocated or removing from the screen any dialog box that it displayed.
  14970.  
  14971. The following status messages can be sent to your status routine by the
  14972. DBGetQueryResults function:
  14973.  
  14974. DBGetQueryResults 
  14975. message             Description
  14976. kDBGetItemComplete  The DBGetItem function has completed execution. When the
  14977. DBGetQueryResults function calls your status routine with this message, the
  14978. result parameter contains the result code returned by the DBGetItem function,
  14979. the dataLen, dataPlaces, and dataType parameters contain the length, decimal
  14980. places, and type of the data item retrieved, the dataFlags parameter has the
  14981. value kDBLastColFlag (that is, the least significant bit is set to 1) if the
  14982. data item is in the last column of the row, and the dataPtr parameter contains a
  14983. pointer to the data item. You can use this information, for example, to check
  14984. the data to see if it meets some criteria of interest to the user, or to display
  14985. each data item as the DBGetItem function receives it.
  14986.  
  14987. The DBGetQueryResults function returns a results record, which contains a handle
  14988. to the retrieved data. The address in the dataPtr parameter points inside the
  14989. array specified by this handle. Because the dataPtr parameter is not a pointer
  14990. to a block of memory allocated by the Memory Manager, but just a pointer to a
  14991. location inside such a block, you cannot use this pointer in any Memory Manager
  14992. routines (such as GetPtrSize). Note also that you cannot rely on this pointer
  14993. remaining valid after you return control to the DBGetQueryResults function. 
  14994.  
  14995. For each data item that it retrieves, the DBGetQueryResults function calls the
  14996. DBGetItem function twice: once to obtain information about the next data item
  14997. and once to retrieve the data item. The DBGetQueryResults function calls your
  14998. status routine only after calling the DBGetItem function to retrieve a data
  14999. item.
  15000.  
  15001. If your status routine returns a function result of FALSE in response to the
  15002. kDBGetItemComplete message, the results record returned by the DBGetQueryResults
  15003. function to your application contains data through the last full row retrieved.
  15004.  
  15005. Data types and results records are described in “Getting Query Results” later in
  15006. this chapter.
  15007.  
  15008. kDBGetQueryResultsComplete
  15009.  
  15010. The DBGetQueryResults function has completed execution and is about to return
  15011. control to your application. The function result is in the result parameter
  15012. passed to your status routine. Your status routine can use this opportunity to
  15013. peform any final tasks, such as  disposing of memory that it allocated or
  15014. removing from the screen any dialog box that it displayed.
  15015.  
  15016. The values of the result, dataLen, dataPlaces, dataFlags, dataType, and dataPtr
  15017. parameters passed to your status routine depend on the value of the message
  15018. parameter, as mentioned in the discussions of the messages and as summarized in
  15019. Table 7-1.
  15020.  
  15021. Table 7-1.  Values of parameters passed to a status routine 
  15022.  
  15023. Message result      dataLen            dataPlaces   dataFlags    dataPtr
  15024.                                                     dataType
  15025.  
  15026. kDBUpdateWind       NIL                NIL           NIL         NIL
  15027. kDBAboutToInit      NIL                NIL           NIL         NIL
  15028. kDBInitComplete     DBInit result      NIL           NIL         NIL
  15029. kDBSendComplete     DBSend result      NIL           NIL         NIL
  15030. kDBExecComplete     DBExec result      NIL           NIL         NIL
  15031. kDBGetItemComplete  DBGetItem result   item info    item type    pointer to item
  15032. kDBGetQueryResultsComplete
  15033.                     DBGetQueryResults result  
  15034.                                        NIL           NIL         NIL           
  15035.  
  15036.  
  15037. Listing 7-2 shows a status routine. This routine updates the application’s
  15038. windows in response to the kDBUpdateWind message, displays a dialog box giving
  15039. the user the option of canceling before the database access is initiated, and
  15040. checks the results of calls to the DBInit, DBSend, DBExec, and DBGetItem
  15041. functions. If one of these functions returns an error, the status routine
  15042. displays a dialog box describing the error.
  15043.  
  15044. Listing 7-2.  A sample status routine (TO BE PROVIDED)
  15045.  
  15046. _______________________________________________________________________________
  15047.  
  15048. æKY Using…the…Low-Level…Interface
  15049. æC »Using the Low-Level Interface                                  Database Access Manager
  15050. _______________________________________________________________________________
  15051.  
  15052. You can use the low-level interface to establish communication (initiate a
  15053. session) with a remote database server, send a query to the database server,
  15054. execute the query, and retrieve any data requested by the query. You must call
  15055. one or more low-level routines to accomplish each of these tasks. 
  15056. Figure 7-6 is a flowchart of a typical session using the low-level interface.
  15057.  
  15058. ø 7.6  Flowchart of session using low-level interface
  15059.  
  15060. As Figure 7-6 illustrates, you must follow this procedure to use the low-level
  15061. interface:
  15062.  
  15063. 1.  Call the InitDBPack function to initialize the Database Access Manager.
  15064.  
  15065. 2.  Call the DBInit function to establish communication with the remote database
  15066. server. The DBInit function returns an identification number, called a session
  15067. ID. This session ID is unique; no other current session, for any database
  15068. extension, has the same session ID. You must specify the session ID any time you
  15069. want to send data to or retrieve data from this session. 
  15070.  
  15071. The DBInit function requires as input parameters the name of the database
  15072. extension and character strings for the remote system, user name, password, and
  15073. connection string. All of these parameters depend on the user and the user’s
  15074. computer system, including the specific database extension, remote computer,
  15075. database server, and database management software in use. You will not know the
  15076. user name and password when you are writing an application, and you might not
  15077. know the values of any of these parameters. Therefore, you must display a dialog
  15078. box that prompts the user for the necessary information.  
  15079.  
  15080. Depending on the database extension you are using, the DBInit function might
  15081. return a session ID of 0 if it fails to initiate a session, or it might return a
  15082. nonzero session ID and a result code other than noErr. In the latter case, you
  15083. can pass the session ID to the DBGetErr function to determine the cause of the
  15084. error. If the DBInit function returns a nonzero session ID and a result code
  15085. other than noErr, you must call the DBEnd function before making another attempt
  15086. to open the session or closing the Database Access Manager.
  15087.  
  15088. 3.  Prepare a query, and send it to the database server by calling the DBSend
  15089. and DBSendItem functions one or more times. 
  15090.  
  15091. An application that uses the low-level interface must be capable of creating a
  15092. query for the database server in the language and format required by that
  15093. database server.
  15094.  
  15095. The DBSend function sends a query or a portion of a query to the remote database
  15096. server. The database server appends this portion of the query to any portion you
  15097. sent previously. Because the Database Access Manager and database server do not
  15098. modify the string you send in any way, they do not insert any delimiter between
  15099. fragments of queries that you send to the database server. If you want a blank
  15100. or a semicolon to be included between query fragments, or if you want to use
  15101. return characters to divide the query into lines of text, you must include them
  15102. in the character string that you send with the DBSend function. The data string
  15103. that you can send with the DBSend function can be any length up to 64 KB.
  15104.  
  15105. The DBSendItem function sends a single data item to the remote database server.
  15106. Use the DBSendItem function to send data items to the database in the same
  15107. format as they are retrieved from the database by the DBGetItem function. You
  15108. must specify the data type as an input parameter and, for any data type that
  15109. does not have an implied length, you must specify the length as well. The
  15110. database extension or the database server (depending on how the system is
  15111. implemented) converts the data item to a character string and appends it to the
  15112. query, just as a query program fragment is appended to the query by the DBSend
  15113. function. 
  15114.  
  15115. You can call the DBSend and DBSendItem functions as many times as you wish to
  15116. send your query to the database server.
  15117.  
  15118. Listing 7-3 sends the CL/1 query fragment “print 451+222;” to the remote CL/1
  15119. server.
  15120.  
  15121. Listing 7-3.  Sending a query fragment
  15122.  
  15123. FUNCTION SendFragment (sessID: LongInt) : OSErr;
  15124.  
  15125. VAR 
  15126.   value1,value2: LongInt;
  15127.   text1, text2, text3: Str15;
  15128.   len1, len2, len3: Integer;
  15129.   rc: OSErr;
  15130.  
  15131. BEGIN
  15132.   text1 := 'print ';
  15133.   len1 := LENGTH(text1);
  15134.   value1 := 451;
  15135.   text2 := '+';
  15136.   len2 := LENGTH(text2);
  15137.   value2 := 222;
  15138.   text3 := ';';
  15139.   len3 := LENGTH(text3);
  15140.   rc := DBSend(sessID, P2CStr(POINTER(ORD(@text1))), len1, NIL);
  15141.  
  15142.   IF rc = noErr THEN
  15143.   rc := DBSendItem(sessID, typeInteger, 0, 0, 0, POINTER(ORD(@value1)), NIL);
  15144.  
  15145.   IF rc = noErr THEN
  15146.   rc := DBSend(sessID, P2CStr(POINTER(ORD(@text2))), len2, NIL);
  15147.  
  15148.   IF rc = noErr THEN
  15149.   rc := DBSendItem(sessID, typeInteger, 0, 0, 0, POINTER(ORD(@value2)), NIL);
  15150.  
  15151.   IF rc = noErr THEN
  15152.   rc := DBSend(sessID, P2CStr(POINTER(ORD(@text3))), len3, NIL);
  15153.  
  15154.   SendFragment := rc;
  15155. END;
  15156.  
  15157. 4.  Use the DBExec function to initiate execution of the query. 
  15158.  
  15159. Depending on the way the system you are using is implemented, the DBExec
  15160. function might return control to your application as soon as the query has begun
  15161. execution. 
  15162.  
  15163. 5.  Use the DBState function to determine the status of the database. 
  15164.  
  15165. The DBState function tells you when the database has finished executing the
  15166. query you just sent. If you have requested data, the database server stores the
  15167. data you requested but does not send it to your application until you request it
  15168. explicitly. The DBState function tells you when the data is available; go on to
  15169. step 6. If you have just called the DBExec function to execute a query and wish
  15170. to send another query, return to step 3. If you are finished using the database,
  15171. skip to step 7.
  15172.  
  15173. 6.  Call the DBGetItem function repeatedly to retrieve the data. 
  15174.  
  15175. The DBGetItem function retrieves the next data item from the database server.
  15176. You can also use this function to obtain information about the next data item
  15177. without retrieving the data. When you use the DBGetItem function to retrieve a
  15178. data item, you must specify the location and size of the buffer into which the
  15179. function is to place that item. If you know beforehand what kind of data to
  15180. expect, you can allocate a buffer of the exact size you need. If you do not know
  15181. what type of data to expect, you can first call the DBGetItem function with a
  15182. NIL pointer to the data buffer. The DBGetItem function then returns information
  15183. about the next data item without actually retrieving it. You can then allocate
  15184. the appropriate buffer and call DBGetItem again. 
  15185.  
  15186. Alternatively, to avoid calling DBGetItem twice for each data item, you can
  15187. allocate a buffer that you expect to be of sufficient size for any data item and
  15188. call the DBGetItem function. If the buffer is not large enough for the data
  15189. item, the DBGetItem function returns the rcDBError result code, but still
  15190. returns information about the data item. You can then allocate the necessary
  15191. buffer, call the DBUnGetVal function to go back one data item, and call the
  15192. DBGetItem function again to retrieve the data item a second time.
  15193.  
  15194. The DBGetItem function includes a timeout parameter that you can use to specify
  15195. the maximum amount of time that the database extension should wait to receive
  15196. results from the database server before canceling the command. If the database
  15197. extension you are using does not support asynchronous execution of routines, you
  15198. can use the timeout parameter to return control to your application while a
  15199. query is executing. To use the timeout parameter in this way, call the DBGetItem
  15200. function periodically with a short value set for the timeout parameter. Your
  15201. application can then retrieve the next data item as soon as execution of the
  15202. query is complete without having to call the DBState function to determine when
  15203. data is available. The DBGetItem function ignores the timeout parameter if you
  15204. make an asynchronous call to this function.
  15205.  
  15206. 7.  When you are finished using the database, you must use the DBEnd function to
  15207. terminate the session. You must call the DBEnd function after the DBInit
  15208. function has returned a nonzero session ID, even if it also returned an error.
  15209.  
  15210. 8.  When you are finished using the Database Access Manager, call the QuitDBPack
  15211. function to close the manager.
  15212.  
  15213. Listing 7-4 uses the low-level interface to send a CL/1 routine to the CL/1
  15214. server on a remote computer, and retrieves the results. 
  15215.  
  15216. Listing 7-4.  Use of the low-level interface (TO BE PROVIDED)
  15217.  
  15218. Note that, even if you are using the low-level interface to send queries to the
  15219. database, you might want to use the high-level functions to retrieve data and
  15220. convert it to text.
  15221.  
  15222. _______________________________________________________________________________
  15223.  
  15224. æKY Getting…Information…About…Sessions…in…Progress
  15225. æC »Getting Information About Sessions in Progress                 Database Access Manager
  15226. _______________________________________________________________________________
  15227.  
  15228. If your application is only one of several on a single Macintosh computer using
  15229. remote databases, you can use the DBGetConnInfo and DBGetSessionNum functions to
  15230. obtain information about the sessions in progress. If you know the session ID 
  15231. (which is returned by the DBInit function when you open a session), you can use
  15232. the DBGetConnInfo function to determine the database extension being used, the
  15233. name of the remote system on which the session is running, the user name and
  15234. connection string that were used to initiate the session, the time at which the
  15235. session started, and the status of the session. The status of the session
  15236. specifies whether the remote database server is executing a query or waiting for
  15237. another query fragment, whether there is output data available, and whether
  15238. execution of a query ended in an error.
  15239.  
  15240. If you do not know the session ID, or if you want to get information about all
  15241. open sessions, you can specify a database extension and a session number when
  15242. you call the DBGetConnInfo function. Although there can be only one active
  15243. session with a given session ID, session numbers are unique only for a specific
  15244. database extension. Because the database extension assigns session numbers
  15245. sequentially, starting with 1, you can call the DBGetConnInfo function
  15246. repeatedly for a given database extension, incrementing the session number each
  15247. time, to obtain information about all sessions open for that database extension.
  15248. Your application need not have initiated the session to obtain information about
  15249. it in this fashion.
  15250.  
  15251. The DBGetSessionNum function returns the session number when you specify the
  15252. session ID. You can use this function to determine the session numbers for the
  15253. sessions opened by your own application. You might want this information, for
  15254. example, so you can distinguish your own sessions from those opened by other
  15255. applications when you use the DBGetConnInfo function to get information about
  15256. all open sessions. 
  15257. _______________________________________________________________________________
  15258.  
  15259. æKY Processing…Query…Results
  15260. æC »Processing Query Results                                       Database Access Manager
  15261. _______________________________________________________________________________
  15262.  
  15263. You can use the low-level function DBGetItem to retrieve a single data item
  15264. returned by a query or you can use the high-level function DBGetQueryResults to
  15265. retrieve all of the query results at once. If you use the DBGetQueryResults
  15266. function, you can then use the DBResultsToText function to convert the results
  15267. to ASCII text. The DBResultsToText function calls routines called result
  15268. handlers, which are installed in memory by applications or by initialization
  15269. routines. This section discusses the use of the DBGetItem and DBGetQueryResults
  15270. functions and describes how to write and install a result handler.
  15271.  
  15272. _______________________________________________________________________________
  15273.  
  15274. æKY Getting…Query…Results
  15275. æC »Getting Query Results                                          Database Access Manager
  15276. _______________________________________________________________________________
  15277.  
  15278. The DBGetItem function retrieves a single data item that was returned by a
  15279. database in response to a query. When you call the DBGetItem function, you
  15280. specify the data type to be retrieved. If you do not know what data type to
  15281. expect, you can specify the constant typeAnyType for the dataType parameter, and
  15282. the database server returns the next data item regardless of data type. It also
  15283. returns information about the data item, including data type and length.  
  15284. If you do not know the length of the next data item, you can specify NIL for the
  15285. buffer parameter in the DBGetItem function, and the database server returns the
  15286. data type, length, and number of decimal places without retrieving the data
  15287. item. The next time you call the DBGetItem function with a nonzero value for the
  15288. buffer parameter, the function retrieves the data item. 
  15289.  
  15290. If you want to skip a data item, specify the constant typeDiscard for the
  15291. dataType parameter. Then the next time you call the DBGetItem function, it
  15292. retrieves the following data item.
  15293.  
  15294. You should use the DBGetItem function if you want complete control over the
  15295. retrieval of each item of data. If you want the Database Access Manager to
  15296. retrieve the data for you, use the DBGetQueryResults function instead.
  15297.  
  15298. Table 7-2 shows the 4-byte code used by the Database Access Manager for each
  15299. data type that is currently defined, and the values used for the dataType
  15300. parameter in the DBGetItem function. The writer of a database extension can
  15301. define other data types to support specific databases or database servers.
  15302.  
  15303. Table 7-2.  Data types, constants, and 4-byte codes
  15304.  
  15305. Data type                Constant        Code
  15306.  
  15307. any type                 typeAnyType     $000000
  15308. no more data expected    typeNone        'none'
  15309. Boolean                  typeBoolean     'bool'
  15310. short integer            typeSMInt       'smin'
  15311. integer                  typeInteger     'int '
  15312. short floating point     typeSMFloat     'smfl'
  15313. floating point           typeFloat       'flot'
  15314. date                     typeDate        'date'
  15315. time                     typeTime        'time'
  15316. date and time            typeTimeStamp   'tims'
  15317. character                typeChar        'char'
  15318. decimal number           typeDecimal     'decm'
  15319. money value              typeMoney       'mony'
  15320. variable character       typeVChar       'vchr'
  15321. variable binary          typeVBin        'vbin'
  15322. long character           typeLChar       'lchr'
  15323. long binary              typeLBin        'lbin'
  15324. discard next data item   typeDiscard     'disc'
  15325. unknown                  typeUnknown     'unkn'
  15326. column break             typeColBreak    'cbrk'
  15327. end of line              typeRowBreak    'rbrk'
  15328.  
  15329. Each data type listed in Table 7-2 has a standard definition, shown in Table
  15330. 7-3. For example, if the DBGetItem function returns the constant typeInteger for
  15331. the dataType parameter, you know that the data item represents an integer value
  15332. and that a 4-byte buffer is necessary to hold it. Similarly, if you are using
  15333. DBSendItem function to send to the database server a data item that you identify
  15334. as typeFloat, the database server expects to receive an 8-byte floating-point
  15335. value. 
  15336.  
  15337. Notice that some of these data types are defined to have a specific length 
  15338. (referred to as an (implied length), and some do not. The len parameter of the
  15339. DBSendItem and DBGetItem functions indicates the length of an individual data
  15340. item. The DBGetQueryResults function returns a handle to an array of lengths,
  15341. decimal places, and flags in the colInfo field of the results record. 
  15342.  
  15343. Table 7-3.  Data types defined by the Database Access Manager
  15344.  
  15345. Value of        Length    Definition
  15346. dataType param
  15347.  
  15348. typeAnyType     NA        Any data type (used as an input parameter to the 
  15349.                           DBGetItem function only; never returned by the 
  15350.                           function)
  15351. typeNone        0         Empty 
  15352. typeBoolean     1 byte    TRUE (1) or FALSE (0)
  15353. typeSMInt       2 bytes   Signed integer value
  15354. typeInteger     4 bytes   Signed long integer value
  15355. typeSMFloat     4 bytes   Signed floating-point value
  15356. typeFloat       8 bytes   Signed floating-point value
  15357. typeDate        4 bytes   Date; a long integer value consisting of a year 
  15358.                           (most significant 16 bits), month (8 bits), and day 
  15359.                           (least significant 8 bits) 
  15360. typeTime        4 bytes   Time; a long integer value consisting of an hour 
  15361.                           (0–23; most significant 8 bits) minute (8 bits),
  15362.                           second (8 bits), and hundredths of a second 
  15363.                           (least significant 8 bits)
  15364. typeTimeStamp   8 bytes   Date and time consisting of a long integer followed
  15365.                           by a long integer time value
  15366. typeChar        any       Fixed-length character string not NULL terminated.
  15367.                           The length of the string is defined by the specific
  15368.                           database.
  15369. typeDecimal     any       Packed decimal string. A contiguous string of 4-bit 
  15370.                           nibbles, each of which contains a decimal number,
  15371.                           except for the low nibble of the highest-addressed
  15372.                           byte (that is, the last nibble in the string), which
  15373.                           contains a sign. The value of the sign nibble can be
  15374.                           10, 12, 14, or 15 for a positive number or 11 or 13
  15375.                           for a negative number; we recommend you use 12 for a
  15376.                           positive number and 13 for a negative number. The most
  15377.                           significant digit is the high-order nibble of the
  15378.                           lowest-addressed byte (that is, the first nibble to
  15379.                           appear in the string).
  15380.  
  15381.                           The total number of nibbles (including the sign 
  15382.                           nibble) must be even; therefore, the high nibble of
  15383.                           the highest-addressed byte of a number with an even
  15384.                           number of digits must be 0.
  15385.  
  15386.                           For example, the number +123 is represented as $123C
  15387.                           and the number –1234 is represented as $01234D.
  15388.  
  15389.                           The length of a packed decimal string is defined as
  15390.                           the number of decimal digits in the string, not the
  15391.                           number of bytes. Any extra leading zero and the sign
  15392.                           nibble are not. Therefore, the number +123 has a
  15393.                           length of 3 and the number –1234 has a length of 4.
  15394.                           The length can have any value from 0 through 31.
  15395.  
  15396.                           In addition to the length of a packed decimal string,
  15397.                           each data item has an associated value that indicates
  15398.                           the number of digits that follow the decimal place.
  15399.                           The places parameter in the DBGetItem and DBSendItem
  15400.                           functions indicates the number of decimal places in an
  15401.                           individual data item. The DBGetQueryResults function
  15402.                           returns the number of decimal places.
  15403. typeMoney       any       Same as typeDecimal, but implies a currency amount.
  15404. typeVChar       any       Variable-length character string, NULL terminated.
  15405. typeVBin        any       Not defined. Reserved for future use.
  15406. typeLChar       any       Not defined. Reserved for future use.
  15407. typeLBin        any       Not defined. Reserved for future use.
  15408. typeDiscard     NA        Do not retrieve the next data item (used as an input
  15409.                           parameter to the DBGetItem function only; never
  15410.                           returned by the function)
  15411. typeUnknown     NA        A dummy data type for the result handler that
  15412.                           processes any data type for which no other result
  15413.                           handler is available (used as an input parameter to
  15414.                           the DBInstallResultHandler, DBRemoveResultHandler, 
  15415.                           and DBGetResultHandler functions only; never returned
  15416.                           by the DBGetItem or DBResultsToText functions)
  15417. typeColBreak    NA        A dummy data type for the result handler that the
  15418.                           DBGetQueryResults function calls after each item that
  15419.                           is not the last item in a row (used as an input
  15420.                           parameter to the DBInstallResultHandler,
  15421.                           DBRemoveResultHandler, and DBGetResultHandler
  15422.                           functions only; never returned by the DBGetItem or
  15423.                           DBResultsToText functions)
  15424. typeRowBreak    NA        A dummy data type for the result handler that the
  15425.                           DBGetQueryResults function calls at the end of each
  15426.                           row (used as an input parameter to the
  15427.                           DBInstallResultHandler, DBRemoveResultHandler, and
  15428.                           DBGetResultHandler functions only; never returned by
  15429.                           the DBGetItem or DBResultsToText functions)
  15430.  
  15431. The DBGetQueryResults function retrieves all of the data that was returned by a
  15432. database in response to a query, unless insufficient memory is available to hold
  15433. the data, in which case it retrieves as many complete rows of data as possible.
  15434. The DBGetQueryResults function stores the data in a structure called a results
  15435. record. The results record is defined by the ResultsRecord data type.
  15436.  
  15437. TYPE ResultsRecord = 
  15438. RECORD
  15439.   numRows:   Integer;  {number of rows retrieved}
  15440.   numCols:   Integer;  {number of columns per row}
  15441.   colTypes:  Handle;   {type of data in each column}
  15442.   colData:   Handle;   {array of data items}
  15443.   colInfo:   Handle    {info about each data item}
  15444. END;
  15445.  
  15446. The numRows field in the results record indicates the total number of rows
  15447. retrieved. If the DBGetQueryResults returns a result code other than rcDBValue,
  15448. then not all of the data actually returned by the database was retrieved. This
  15449. could happen, for instance, if the user’s computer does not have sufficient
  15450. memory space to hold all the data. In this case, your application can make more
  15451. space available (by writing the data in the data record to disk, for example)
  15452. and then call the DBGetQueryResults function again to complete retrieval of the
  15453. data.
  15454.  
  15455. Note: The DBGetQueryResults function retrieves whole rows only; if it runs out
  15456. of space in the middle of a row, it stores the partial row in a private buffer
  15457. so that the data in the results record ends with the last complete row. Because
  15458. the last partial row is no longer available from the remote database server, you
  15459. cannot start to retrieve data with the DBGetQueryResults function and then
  15460. switch to the DBGetItem function to complete the data retrieval.
  15461.  
  15462. The numCols field indicates the number of columns in each row of data.
  15463.  
  15464. The colTypes field is a handle to an array of data types, specifying the type of
  15465. data in each column. The number of elements in the array is equal to the value
  15466. in the numCols parameter. Table 7-2 shows the standard data types. 
  15467.  
  15468. The colData field is a handle to the data retrieved by the DBGetQueryResults
  15469. function.
  15470.  
  15471. The colInfo field is a handle to an array of records of type DBColInfoRecord,
  15472. each of which specifies the length, places, and flags for a data item. There are
  15473. as many records in the array as there are data items retrieved by the
  15474. DBGetQueryResults function. Here is the DBColInforRecord type definition:
  15475.  
  15476. TYPE DBColInfoRecord = 
  15477. RECORD
  15478.   len:     Integer;  {length of data item}
  15479.   places:  Integer;  {places for decimal and money data items}
  15480.   flags:   Integer;  {flags for data item}
  15481. END;
  15482.  
  15483. The len field indicates the length of the data item. The DBGetQueryResults
  15484. function returns a value in this field only for those data types that do not
  15485. have implied lengths; see Table 7-3. 
  15486.  
  15487. The places field indicates the number of decimal places in data items of types
  15488. typeMoney and typeDecimal. For all other data types, the places field returns 0.
  15489.  
  15490. If the flags field is set to kDBLastColFlag (that is, the least significant bit
  15491. is set to 1), the data item is in the last column of the row. 
  15492. _______________________________________________________________________________
  15493.  
  15494. æKY Converting…Query…Results…to…Text
  15495. æC »Converting Query Results to Text                               Database Access Manager
  15496. _______________________________________________________________________________
  15497.  
  15498. The DBResultsToText function provided by the high-level interface converts the
  15499. data retrieved by the DBGetQueryResults function into strings of ASCII text.
  15500. This function makes it easier for you to display retrieved data for the user. 
  15501. For the DBResultsToText function to convert data of a specific type to text,
  15502. either the application or the system software must have a routine called a
  15503. result handler. With system software version 7.0, Apple Computer, Inc. is
  15504. providing system result handlers for the data types listed in Table 7-4. These
  15505. data types are described in Table 7-3:
  15506.  
  15507. Table 7-4.  Data types for which system result handlers are provided
  15508.  
  15509. Data type              Result handler   Data type code
  15510.  
  15511. Boolean                typeBoolean      'bool'
  15512. short integer          typeSMInt        'smin'
  15513. integer                typeInteger      'int '
  15514. short floating point   typeSMFloat      'smfl'
  15515. floating point         typeFloat        'flot'
  15516. character              typeChar         'char'
  15517. variable character     typeVChar        'vchr'
  15518.  
  15519. Note that Table 7-3 also defines several other data types for which Apple does
  15520. not provide system result handlers. 
  15521.  
  15522. In addition to these standard data types, Apple is providing the system result
  15523. handlers shown in Table 7-5.
  15524.  
  15525.   •   typeUnknown  
  15526.   •   typeColBreak   
  15527.   •   typeRowBreak 
  15528.  
  15529. Table 7-5.  Additional system result handlers
  15530.  
  15531. Data type      Result handler   Data type code
  15532.  
  15533. unknown        typeUnknown     'unkn'
  15534. column break   typeColBreak     'cbrk'
  15535. end of line    typeRowBreak     'rbrk'
  15536.  
  15537. The typeUnknown result handler processes any data type for which no other result
  15538. handler is available. The DBResultsToText function calls the typeColBreak result
  15539. handler after each item that is not the last item in a row. This result handler
  15540. does not correspond to any data type, but adds a delimiter character to separate
  15541. columns of text. The default typeColBreak result handler inserts a tab
  15542. character. Similarly, the DBResultsToText function calls the typeRowBreak result
  15543. handler at the end of each row of data to add a character that separates the
  15544. rows of text. The default typeRowBreak result handler inserts a return
  15545. character. Your application can install result handlers for the typeColBreak and
  15546. typeRowBreak data types to insert whatever characters you wish—or to insert no
  15547. character at all, if you prefer.
  15548.  
  15549. You can install result handlers for any data types you know about. When you call
  15550. the DBInstallResultHandler function, you can specify whether the result handler
  15551. you are installing is a system result handler. A system result handler is
  15552. available to all applications that use the system. All other result handlers 
  15553. (called application result handlers) are associated with a particular
  15554. application. The DBResultsToText function always uses a result handler for the
  15555. current application in preference to a system result handler for the same data
  15556. type. When you install a system result handler with the same name as an already
  15557. installed system result handler, the new result handler replaces the old one.
  15558. Similarly, when you install an application result handler with the same name as
  15559. a result handler already installed for the same application, the new result
  15560. handler replaces the old one for that application. 
  15561.  
  15562. Result handlers are stored in memory. The Database Access Manager reinstalls its
  15563. system result handlers each time the Macintosh Operating System loads the
  15564. Database Access Manager package into memory. You must reinstall your own
  15565. application result handlers each time your application starts up. You can also
  15566. install your own system result handlers each time your application starts up, or
  15567. you can provide an initialization file (that is, a file with a resource of type
  15568. 'INIT' that is placed in the System Folder) that installs system result handlers
  15569. each time the user starts up the system.
  15570.  
  15571. Here is a function declaration for a result handler function.
  15572.  
  15573. FUNCTION MyResultHandler (dataType: DBType; theLen,thePlaces, theFlags:
  15574.                           Integer; theData: Ptr; theText: Handle) : OSErr;
  15575.  
  15576. The dataType parameter specifies the data type of the data item that the
  15577. DBResultsToText function is passing to the result handler. Table 7-3 describes
  15578. the standard data types. 
  15579.  
  15580. The parameters theLen and thePlaces specify the length and number of decimal
  15581. places of the data item that the DBResultsToText function wants the result
  15582. handler to convert to text. 
  15583.  
  15584. The parameter theFlags is the value returned for the flags parameter by the
  15585. DBGetItem function. If this parameter is set to kDBLastColFlag (that is, the
  15586. least significant bit is set to 1), the data item is in the last column of the
  15587. row. 
  15588.  
  15589. The parameter theData is a pointer to the data that the result handler is to
  15590. convert to text.
  15591.  
  15592. The parameter theText is a handle to the buffer that is to hold the text version
  15593. of the data. The result handler should use the SetHandleSize function to
  15594. increase the size of the buffer as necessary to hold the new text, and append
  15595. the new text to the end of the text already in the buffer. The SetHandleSize
  15596. function is described in the Memory Manager chapter of Volume II.
  15597.  
  15598. If the result handler successfully converts the data to text, it should return a
  15599. result code of 0 (noErr). 
  15600. You can use the DBInstallResultHandler function to install a result handler and
  15601. the DBRemoveResultHandler function to remove an application result handler. You
  15602. can install and replace system result handlers, but you cannot remove them. 
  15603.  
  15604. The following line of code installs an application result handler. The first
  15605. parameter (typeMoney) specifies the data type that this result handler
  15606. processes. The second parameter (moneyPtr) is a pointer to the result handler
  15607. routine. The last parameter (FALSE) is a boolean specifying that this routine is
  15608. not a system result handler.
  15609.  
  15610. err := DBInstallResultHandler (typeMoney, moneyPtr, FALSE);
  15611.  
  15612. Listing 7-5 shows a result handler that converts data to text.
  15613.  
  15614. Listing 7-5.  A result handler (TO BE PROVIDED)
  15615.  
  15616. _______________________________________________________________________________
  15617.  
  15618. æKY Creating…a…Query…Document
  15619. æC »CREATING A QUERY DOCUMENT                                      Database Access Manager
  15620. _______________________________________________________________________________
  15621.  
  15622. A query document is a file of type 'qery' that contains a 'qrsc' resource and
  15623. one or more 'wstr' resources, and may contain a 'qdef' resource plus other
  15624. resources. Query documents make it possible for you to write applications that
  15625. can communicate with remote database servers without requiring familiarity with
  15626. CL/1 or another database connectivity language. Because a query document is most
  15627. useful if it can be used by many different applications, no query document
  15628. should depend on the presence of a particular application in order to function.
  15629.  
  15630. An application can call the DBGetNewQuery function to convert a 'qrsc' resource
  15631. into a query record in memory. The query record points to a 'wstr' resource that
  15632. contains a template for a query; it contains the database commands and data
  15633. necessary to create a query, without any information that must be added by the
  15634. user just before the query is sent. The 'qdef' resource contains a query
  15635. definition function, which can modify the query record and the can complete the
  15636. query template to create a complete query. The DBStartQuery function sends the
  15637. query pointed to by a query record to a remote database server. This section
  15638. describes the contents of a query document, describes query records, and defines
  15639. the 'qrsc', 'wstr', and 'qdef' resources.
  15640.  
  15641. _______________________________________________________________________________
  15642.  
  15643. æKY Contents…of…a…Query…Document
  15644. æC »Contents of a Query Document                                   Database Access Manager
  15645. _______________________________________________________________________________
  15646.  
  15647. The query document must contain
  15648.  
  15649.   •   a 'qrsc' resource, as defined in the next section, “Query Records and
  15650.       Query Resources”
  15651.  
  15652.   •   a 'STR#' resource that contains the name of the database extension to be
  15653.       used, plus the host, user name, password, and connection string used by
  15654.       the DBInit function
  15655.  
  15656.   •   one or more 'wstr' resources containing queries; that is, strings of
  15657.       commands and data that the DBSend function sends to the remote database
  15658.       server and that the DBExec function executes
  15659.  
  15660. A 'wstr' resource consists of a 2-byte length field followed by a character
  15661. string. (The w in 'wstr' refers to the length word as opposed to the length byte
  15662. used in a 'STR ' resource.) Each 'wstr' resource contains one query (or one
  15663. query template, to be modified by the query definition function before it is
  15664. sent to the remote database server). The 'qrsc' resource includes an array that
  15665. lists the resource ID numbers of all of the 'wstr' resources in the query
  15666. document and an index into the array that specifies which one of the 'wstr'
  15667. resources should be sent to the database server.
  15668.  
  15669. In addition, the query document may contain
  15670.  
  15671.   •   a 'qdef' resource that contains a query definition function
  15672.  
  15673.   •   any resources needed by the query definition function, such as 'DLOG' and
  15674.       'DITL' resources (which support dialog boxes)
  15675.  
  15676. Figure 7-7 illustrates the relationship between a query document, the query
  15677. record, and the query definition function. The following sections describe
  15678. 'qrsc' resources, query records, and 'qdef' resources in detail. 
  15679.  
  15680. ø 7.7  Relationship between a query document, a query record, and  a query
  15681. definition function
  15682. _______________________________________________________________________________
  15683.  
  15684. æKY Query…Records…and…Query…Resources
  15685. æC »Query Records and Query Resources                              Database Access Manager
  15686. _______________________________________________________________________________
  15687.  
  15688. The DBGetNewQuery function converts the 'qrsc' resource on disk into a query
  15689. record in memory. The query definition function can then modify the query record
  15690. before the application sends the query to the remote database server. This
  15691. section describes a query record, and then defines the format of a 'qrsc'
  15692. resource. The following section, “Writing a Query Definition Function,”
  15693. describes 'qdef' resources and query definition functions.
  15694.  
  15695. _______________________________________________________________________________
  15696.  
  15697. æKY Query…Records
  15698. æC »Query Records                                                  Database Access Manager
  15699. _______________________________________________________________________________
  15700.  
  15701. The QueryRecord data structure defines a query record.
  15702.  
  15703. TYPE QueryRecord = 
  15704. Record
  15705.   version:     Integer;          {query record format version}
  15706.   id:          Integer;          {resource ID of 'qrsc'}
  15707.   queryProc:   Handle;           {handle to qdef}
  15708.   ddevName:    Str63;            {name of ddev}
  15709.   host:        Str255;           {name of remote computer}
  15710.   user:        Str255;           {name of user}
  15711.   password:    Str255;           {user's password}
  15712.   connStr:     Str255;           {connection string}
  15713.   currQuery:   Integer;          {current query}
  15714.   numQueries:  Integer;          {number of queries}
  15715.   queryList:   QueryListHandle;  {handles to queries}
  15716.   numRes:      Integer;          {number of resources}
  15717.   resList:     ResListHandle;    {list of resources}
  15718.   dataHandle:  Handle;           {handle to memory for qdef}
  15719.   refCon:      LongInt           {reserved for use by app}
  15720. END;
  15721.  
  15722. Field descriptions
  15723. version
  15724. The version number of the query record format. For the Database Access Manager
  15725. released with system software version 7.0, the version number is 0.
  15726.  
  15727. id
  15728. The resource ID of the 'qrsc' resource from which the Database Access Manager
  15729. created this query record.
  15730.  
  15731. queryProc
  15732. A handle to the query definition function that the DBStartQuery function calls.
  15733. This handle is NIL if there is no query definition function; that is, if the
  15734. DBStartQuery function should send the query specified by this query record to
  15735. the remote database server without modifications.
  15736.  
  15737. ddevName
  15738. The database extension name used as a parameter to the DBInit function. 
  15739. host  The name of the remote computer system used as a parameter to the DBInit
  15740. function. 
  15741.  
  15742. user
  15743. The name of the user, used as a parameter to the DBInit function.
  15744.  
  15745. password
  15746. The user’s password, used as a parameter to the DBInit function. 
  15747.  
  15748. connStr
  15749. The connection string used as a parameter to the DBInit function. 
  15750.  
  15751. currQuery
  15752. An index value from 1 through numQueries, indicating which element in the array
  15753. of query handles represents the current query. The current query is the one
  15754. actually sent to the database server. If the query document contains more than
  15755. one 'wstr' resource, the query definition function can prompt the user to select
  15756. a new current query and modify this field in the query record appropriately. 
  15757. numQueries  The number of queries referred to by the queryList field.
  15758.  
  15759. queryList
  15760. A handle to an array of handles. Each handle in this array refers to a query.
  15761. Each query is created from a 'wstr' resource in the query document and is stored
  15762. in memory as a 2-byte length field followed by ASCII text. (The length does not
  15763. include the 2 bytes of the length field.) The query definition function can
  15764. create a new query. To add a new handle to the array of handles, use the Memory
  15765. Manager’s SetHandleSize function to increase the size of the array. Don’t forget
  15766. to change the value of the numQueries field as well.
  15767.  
  15768. numRes
  15769. The number of resources referred to by the resList field.
  15770.  
  15771. resList
  15772. A handle to an array of records of type ResListElem. Each record in the array
  15773. contains the type and ID of a resource that is needed by the query definition
  15774. function. 
  15775.  
  15776. TYPE ResListElem = 
  15777. RECORD
  15778.   TheType:  ResType;  {resource type}
  15779.   id:       Integer   {resource ID}
  15780. END;
  15781.  
  15782. dataHandle
  15783. A handle to memory for use by the query definition function. When the Database
  15784. Access Manager first creates the query record, this field is NIL. The query
  15785. definition function can allocate memory and place a handle to it in this field.
  15786. The query definition function should dispose of any memory it allocates before
  15787. it returns control to the Database Access Manager.
  15788.  
  15789. refCon
  15790. The query record’s reference value. The application can use this field for any
  15791. purpose.
  15792.  
  15793. _______________________________________________________________________________
  15794.  
  15795. æKY Query…Resources
  15796. æC »Query Resources                                                Database Access Manager
  15797. _______________________________________________________________________________
  15798.  
  15799. Here is the structure of the 'qrsc' resource, in the format used by the Rez
  15800. resource compiler supplied with MPW.
  15801.  
  15802. type 'qrsc' {
  15803. Integer;  /* version */
  15804. Integer;  /* ID of 'qdef' resource */
  15805. Integer;  /* ID of 'STR#' resource that contains ddevName, host, user, password,
  15806.             connection string */
  15807. Integer;  /* current query */
  15808.  
  15809. /* Array of IDs of 'wstr' resources that contain queries */
  15810.  
  15811. Integer = $$CountOf(QueryArray);  /* array size */
  15812. wide array QueryArray{
  15813.                       Integer;    /* ID of 'wstr' resource */
  15814. };
  15815.  
  15816. /* Array of resource types and IDs for other resources in the query document */
  15817.  
  15818. Integer = $$CountOf(ResArray);  /* array size */
  15819. wide array ResArray{
  15820.             literal LongInt;    /* resource type */
  15821.             Integer;            /* resource ID */
  15822. };
  15823. };
  15824.  
  15825. The first field in the 'qrsc' resource is the version number of the 'qrsc'
  15826. format. For the Database Access Manager released with system software version
  15827. 7.0, the version number is 0.
  15828.  
  15829. The second field is the resource ID of the 'qdef' resource containing the query
  15830. definition function that the Database Access Manager is to call when it opens
  15831. this 'qrsc' resource. Use an ID of 0 if there is no query definition function
  15832. for this resource; that is, if the Database Access Manager should send the query
  15833. in this resource to the remote database server without modifications.
  15834.  
  15835. The third field is the ID of a 'STR#' resource that contains five Pascal strings
  15836. corresponding to the parameters used by the DBInit function. If the query
  15837. definition function is going to prompt the user for the values of these
  15838. parameters before entering them in the query record, they should be zero-length
  15839. strings in the 'STR#' resource.
  15840.  
  15841. The sixth field in the 'qrsc' resource is an array of ID numbers of the 'wstr'
  15842. resources in the query document. The fifth field is the size of the array of
  15843. 'wstr' IDs, and the fourth field is an index value indicating which element in
  15844. the array of 'wstr' IDs represents the current query. (The array elements are
  15845. numbered starting with 1.) The current query is the one actually sent to the
  15846. database server. If the query document contains more than one 'wstr' resource,
  15847. the query definition function can prompt the user to select the query to use and
  15848. modify the current query field in the query record appropriately.
  15849.  
  15850. The eighth field in the 'qrsc' resource is an array listing the resource types
  15851. and IDs of all the resources in the query document other than the standard
  15852. resources included in all query documents. The seventh field is the size of this
  15853. array. The resources listed in this final array are those used by the query
  15854. definition function. This list should include resources embedded in other
  15855. resources, such as a 'PICT' resource that is included in a 'DITL' resource. 
  15856. _______________________________________________________________________________
  15857.  
  15858. æKY Writing…a…Query…Definition…Function
  15859. æC »Writing a Query Definition Function                            Database Access Manager
  15860. _______________________________________________________________________________
  15861.  
  15862. When the Database Access Manager creates a query record, it calls the query
  15863. definition function specified by the queryProc field in the query record. The
  15864. purpose of the query definition function is to modify the query and the query
  15865. record before the query is sent to the remote database server. The query
  15866. definition function can use dialog boxes to request information from the user.
  15867. Because a query document is most useful if it can be used by many different
  15868. applications, no query definition function should depend on the presence of a
  15869. particular application.
  15870.  
  15871. If you want to include a query definition function, you must make it the first
  15872. piece of code in a resource of type 'qdef' in the query document. 
  15873. Here is a function declaration for a query definition function.
  15874.  
  15875. FUNCTION myqdef (VAR sessID: LongInt; query: QueryHandle) : OSErr;
  15876.  
  15877. If the application has already established a session with the remote database
  15878. server, the DBStartQuery function passes the session ID for that session in the
  15879. sessID parameter to the query definition function. If the query definition
  15880. function receives a 0 in this parameter, then the Database Access Manager has
  15881. not established a session. In this case, the query definition function can
  15882. return a 0 in the sessID parameter, or it can call the DBInit function to
  15883. establish a session and then return the session ID in this parameter. 
  15884. If the query definition function returns a 0 in the sessID parameter, the
  15885. DBStartQuery function calls the DBInit function and then calls the DBSend
  15886. function to send a query to the remote database server. If the query definition
  15887. function returns a session ID in this parameter, the DBStartQuery function calls
  15888. the DBSend function immediately.
  15889.  
  15890. The query parameter to the query definition function specifies a handle to the
  15891. query record. The query definition function can modify any of the fields in the
  15892. query record, including the currQuery field that specifies which query is to be
  15893. sent to the remote database server. In addition, the query definition function
  15894. can modify an existing query or create a new query, adding the handle to the new
  15895. query to the query list. Note that, because a query in memory consists only of a
  15896. 2-byte length value followed by a character string, the query definition
  15897. function has to know the exact contents and structure of a query in order to
  15898. modify it.
  15899.  
  15900. The query definition function must return the noErr result code as the function
  15901. result if the function executed successfully. If it returns any other value, the
  15902. DBStartQuery function does not call the DBSend function. The query definition
  15903. function can return any result code, including
  15904.  
  15905.   noErr               0  No error
  15906.   userCanceledErr  –128  User canceled the query
  15907.   rcDBError        –802  Error executing query definition function
  15908.  
  15909. When the DBStartQuery function calls the query definition function, the current
  15910. resource file is the file that contains the 'qrsc' resource from which the
  15911. Database Access Manager created the query record. When the query definition
  15912. function returns control to the Database Access manager, the current resource
  15913. file must be unchanged. 
  15914.  
  15915. The query definition function can allocate memory and use the dataHandle field
  15916. in the query record to store a handle to it; the function can also use the
  15917. refCon field in the query record for any purpose. The query definition function
  15918. must free any memory it allocates before terminating.
  15919.  
  15920. Listing 7-6 shows a query definition function.
  15921.  
  15922. Listing 7-6.  A query definition function (TO BE PROVIDED)
  15923.  
  15924. _______________________________________________________________________________
  15925.  
  15926. æKY Database…Access…Manager…Routines
  15927. æC »DATABASE ACCESS MANAGER ROUTINES                               Database Access Manager
  15928. _______________________________________________________________________________
  15929.  
  15930. The Database Access Manager has high-level routines, low-level routines, and
  15931. routines that manipulate result handlers. This section describes all of the
  15932. Database Access Manager routines.
  15933.  
  15934. All of the low-level routines and some of the high-level routines have as a
  15935. parameter a pointer to an asynchronous parameter block. If you specify a nonzero
  15936. value for this parameter, the database extension executes the function
  15937. asynchronously; that is, it returns control to the Database Access Manager
  15938. before the routine has completed execution, and the Database Access Manager
  15939. returns control to your application.  If you specify NIL for the pointer to the
  15940. asynchronous parameter block, the database extension does not return control to
  15941. your application until the routine has finished execution.Your application must
  15942. call the WaitNextEvent routine periodically to allow an asynchronous routine to
  15943. complete execution. The WaitNextEvent routine is described in the Event Manager
  15944. chapter of this volume.
  15945.  
  15946. You can tell when an asynchronous routine has completed execution and check the
  15947. result code by looking at values in the asynchronous parameter block. The
  15948. asynchronous parameter block is described in the next section, “Asynchronous
  15949. Execution of Routines.” 
  15950.  
  15951. Note:   A noErr result code returned by a routine that has been called
  15952. asynchronously indicates only that the routine began execution successfully. You
  15953. must check the result field of the asynchronous parameter block for the final
  15954. result of the routine.
  15955.  
  15956. Assembly-language note:  You can invoke each of the Database Access Manager
  15957. routines with a macro that has the same name as the routine, but preceded with
  15958. an underscore; for example, the macro for the DBInit function is named _DBInit.
  15959. Each of these macros places a routine selector in the D0 register and calls the
  15960. trap _Pack13. The routine selectors are listed in “Summary of the Database
  15961. Access Manager” at the end of this chapter.
  15962.  
  15963. _______________________________________________________________________________
  15964.  
  15965. æKY Asynchronous…Execution…of…Routines
  15966. æC »Asynchronous Execution of Routines                             Database Access Manager
  15967. _______________________________________________________________________________
  15968.  
  15969. Each Database Access Manager routine that can be called asynchronously (that is,
  15970. that can return control to your application before it has completed execution)
  15971. takes as a parameter a pointer to a parameter block known as the asynchronous
  15972. parameter block. If this pointer is NIL, the routine does not return control to
  15973. your application until it has completed execution.
  15974.  
  15975. Note:  The asynchronous parameter block is passed on to the database extension,
  15976. which is responsible for implementing the asynchronous routine. If the database
  15977. extension does not support asynchronous routines, the Database Access Manager
  15978. returns a result code of rcDBAsyncNotSupp and terminates execution of the
  15979. routine. 
  15980.  
  15981. The DBAsyncParamBlockRec data type defines the asynchronous parameter block.
  15982.  
  15983. TYPE DBAsyncParamBlockRec = 
  15984. RECORD
  15985.   completionProc:  ProcPtr;  {pointer to completion routine}
  15986.   result:          OSErr;    {result of call}
  15987.   userRef:         LongInt;  {reserved for use by application}
  15988.   ddevRef:         LongInt;  {reserved for use by ddev}
  15989.   reserved:        LongInt   {reserved for use by Database Access Mgr}
  15990. END;
  15991.  
  15992. DBAsyncParmBlkPtr = ^DBAsyncParamBlockRec;
  15993.  
  15994. The completionProc field is a pointer to a completion routine that the database
  15995. extension calls when it has completed executing the asynchronous function.
  15996. Before calling the completion routine, the database extension places a pointer
  15997. to the asynchronous parameter block in the A0 register. If you do not want to
  15998. use a completion routine, set this parameter to NIL.
  15999.  
  16000. The database extension sets the result field to 1 while the routine is
  16001. executing, and places the result code in it when the routine completes. An
  16002. application can poll this field to determine when an asynchronous routine has
  16003. completed execution. 
  16004.  
  16005. The userRef field is reserved for the application’s use. Because the database
  16006. extension passes a pointer to the parameter block to the completion routine, you
  16007. can use this field to pass information to the completion routine.
  16008.  
  16009. The ddevRef field is reserved for use by the database extension, and the
  16010. reserved field is reserved for use by the Database Access Manager.
  16011.  
  16012. You can use the DBKill function to cancel an asynchronous routine.
  16013.  
  16014. _______________________________________________________________________________
  16015.  
  16016. æKY Initializing…and…Closing…the…Database…Access…Manager
  16017. æC »Initializing and Closing the Database Access Manager           Database Access Manager
  16018. _______________________________________________________________________________
  16019.  
  16020. You must call the InitDBPack function before you call any other Database Access
  16021. Manager routines. You must call the QuitDBPack function when you are finished
  16022. using the Database Access Manager.
  16023.  
  16024. FUNCTION InitDBPack : OSErr;
  16025.  
  16026. The InitDBPack function causes the Package Manager to load the Database Access
  16027. Manager into memory, if it has not already done so, and increments the Database
  16028. Access Manager use counter. The use counter prevents any application from
  16029. removing the Database Access Manager from memory while another application is
  16030. using it.  
  16031.  
  16032. The interface routine that implements the InitDBPack function includes a version
  16033. number for the Database Access Manager. If the package is a different version
  16034. than specified by the interface routine, then the InitDBPack function returns
  16035. the rcDBWrongVersion result code.
  16036.  
  16037. Result codes
  16038. noErr                0  No error
  16039. rcDBWrongVersion  –814  Wrong version number
  16040.  
  16041. FUNCTION QuitDBPack : OSErr;
  16042.  
  16043. The QuitDBPack function decrements the Database Access Manager use counter. When
  16044. this counter equals 0, the QuitDBPack function removes the Database Access
  16045. Manager package from memory. Call this routine when your application is
  16046. terminating or when you are finished using the Database Access Manager. The use
  16047. counter prevents the QuitDBPack function from removing the Database Access
  16048. Manager from memory while any application is still using it.
  16049.  
  16050. Result codes
  16051. noErr                 0  No error
  16052. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16053. _______________________________________________________________________________
  16054.  
  16055. æKY High-Level…Interface
  16056. æC »High-Level Interface                                           Database Access Manager
  16057. _______________________________________________________________________________
  16058.  
  16059. The high-level interface to the Database Access Manager enables applications to
  16060. manipulate query documents and to get the results of the query provided by a
  16061. query document. The use and contents of query documents are discussed in 
  16062. “Creating a Query Document” earlier in this chapter.
  16063.  
  16064. _______________________________________________________________________________
  16065.  
  16066. æKY Handling…Query…Documents
  16067. æC »Handling Query Documents                                       Database Access Manager
  16068. _______________________________________________________________________________
  16069.  
  16070. The routines described in this section open query documents, create query
  16071. records, dispose of query records, and use query documents to establish
  16072. communication with and send queries to a remote database server.
  16073.  
  16074. FUNCTION DBGetNewQuery (queryID: Integer; VAR query: QueryHandle) : OSErr;
  16075.  
  16076. The DBGetNewQuery function creates a query record from the 'qrsc' resource with
  16077. the resource ID you specify in the queryID parameter. The resource file that
  16078. contains the 'qrsc' resource must remain open until after the DBStartQuery
  16079. function has completed execution. If you do not already know the resource ID of
  16080. the 'qrsc' resource (for example, if you call the SFGetFile procedure to let the
  16081. user select the query document), you can use Resource Manager routines to
  16082. determine the resource ID. The SFGetFile procedure is described in the Standard
  16083. File Package chapter of Volume I and the Resource Manager is described in Volume
  16084. Chapter 5.
  16085.  
  16086. The queryID parameter specifies the resource ID of the 'qrsc' resource that you
  16087. want to use. The query parameter returns a handle to the query record.
  16088.  
  16089. Result code
  16090. noErr                 0  Query record built successfully
  16091. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16092.  
  16093. FUNCTION DBDisposeQuery (query: QueryHandle) : OSErr;
  16094.  
  16095. The DBDisposeQuery function disposes of a query record and frees all the memory
  16096. that the Database Access Manager allocated when it created the query record. You
  16097. should call this function after you are finished using a query record.
  16098.  
  16099. The query parameter is a handle to the query record.
  16100.  
  16101. Result code
  16102. noErr                 0  Query record disposed of successfully
  16103. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16104.  
  16105. FUNCTION DBStartQuery (VAR sessID: LongInt; query: QueryHandle; statusProc:
  16106.                        ProcPtr; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16107.  
  16108. The DBStartQuery function performs the following tasks, in the order specified:
  16109.  
  16110. 1.  It calls the query definition function (if any) pointed to by the query
  16111. record. The query definition function modifies the query record and the query,
  16112. usually by asking the user for input. The query definition function can display
  16113. a dialog box that gives the user the option of canceling the query; if the user
  16114. does cancel the query, the DBStartQuery function returns the userCanceledErr
  16115. result code.
  16116.  
  16117. 2.  If you specify a nonzero value for the statusProc parameter, the
  16118. DBStartQuery function calls your status routine with the value kDBUpdateWind in
  16119. the message parameter so that your application can update its windows.
  16120.  
  16121. 3.  If you specify a nonzero value for the statusProc parameter, the
  16122. DBStartQuery function calls your status routine with the value kDBAboutToInit in
  16123. the message parameter so that your application can display a dialog box
  16124. informing the user that a database session is about to be established, and
  16125. giving the user the option of canceling execution of the function.
  16126.  
  16127. 4.  If the sessID parameter is 0, the DBStartQuery function calls the DBInit
  16128. function to establish a database session, and returns a session ID. 
  16129.  
  16130. 5.  If you specify a nonzero value for the statusProc parameter and the
  16131. DBStartQuery function called the DBInit function, the DBStartQuery function
  16132. calls your status routine with the value kDBInitComplete in the message
  16133. parameter and the result of the DBInit function in the result parameter.
  16134.  
  16135. 6.  The DBStartQuery function calls the DBSend function to send the query to the
  16136. remote database server.
  16137.  
  16138. 7.  If you specify a nonzero value for the statusProc parameter, the
  16139. DBStartQuery function calls your status routine with the value kDBSendComplete
  16140. in the message parameter and the result of the DBSend function in the result
  16141. parameter.
  16142.  
  16143. 8.  The DBStartQuery function calls the DBExec function to execute the query.
  16144.  
  16145. 9.  If you specify a nonzero value for the statusProc parameter, the
  16146. DBStartQuery function calls your status routine with the value kDBExecComplete
  16147. in the message parameter and the result of the DBExec function in the result
  16148. parameter.
  16149.  
  16150. 10.  If you specify a nonzero value for the statusProc parameter, the
  16151. DBStartQuery function calls your status routine with the value
  16152. kDBStartQueryComplete in the message parameter and the result of the
  16153. DBStartQuery function in the result parameter.
  16154.  
  16155. You can use the sessID parameter to specify a session ID if your application or
  16156. another application has already established a session with the database server.
  16157. If you specify NIL for this parameter, then the DBStartQuery function
  16158. establishes a session and returns the session ID in the sessID parameter.
  16159.  
  16160. You use the query parameter to specify a handle to a query record. 
  16161. You can use the statusProc pointer to specify a pointer to a status routine that
  16162. your application can use to update its windows after the query definition
  16163. function has completed execution. If you specify NIL for this parameter, the
  16164. DBStartQuery function does not attempt to update your application’s windows. The
  16165. DBStartQuery function also calls your status routine before it initiates a
  16166. database session, after it calls the DBInit function, after it calls the DBSend
  16167. function, and after it calls the DBExec function. Status routines are discussed
  16168. in “Writing a Status Routine for High-Level Functions” earlier in this chapter.
  16169.  
  16170. If you specify a pointer to an asynchronous parameter block in the asyncPB
  16171. parameter, the DBStartQuery function calls the DBInit, DBSend, and DBExec
  16172. functions asynchronously. As soon as the DBInit function has started execution,
  16173. it returns control to your application. Your application must then call the
  16174. WaitNextEvent routine periodically to allow these asynchronous routines to run,
  16175. and it must check the result field of the asynchronous parameter block to
  16176. determine when each routine has completed execution.
  16177.  
  16178. Result codes
  16179. noErr                 0  No error
  16180. userCanceledErr    –128  User canceled the query 
  16181. rcDBError          –802  Error initiating session, sending text, or executing 
  16182.                          query
  16183. rcDBBadDDev        –809  Couldn’t find the specified database extension, or
  16184.                          error occurred in opening database extension   
  16185. rcDBAsyncNotSupp   –811  The database extension does not support asynchronous
  16186.                          calls
  16187. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16188.  
  16189. _______________________________________________________________________________
  16190.  
  16191. æKY Handling…Query…Results
  16192. æC »Handling Query Results                                         Database Access Manager
  16193. _______________________________________________________________________________
  16194.  
  16195. The routines in this section retrieve query results and convert them to text.
  16196.  
  16197. FUNCTION DBGetQueryResults (sessID: LongInt; VAR results: ResultsRecord;
  16198.                             timeout: LongInt; statusProc: ProcPtr; 
  16199.                             asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16200.  
  16201. The DBGetQueryResults function retrieves the results returned by a query and
  16202. places them in memory. If there is sufficient memory available, this function
  16203. retrieves all of the results at once. If the DBGetQueryResults function runs out
  16204. of memory, it places as much data as possible in memory, up to the last whole
  16205. row. You can then make more memory available and call the DBGetQueryResults
  16206. function again to retrieve more data. 
  16207.  
  16208. The DBGetQueryResults function can be used to retrieve the results of any query,
  16209. not only queries sent and executed by the DBStartQuery function.
  16210.  
  16211. The sessID parameter specifies the ID of the session from which you wish to
  16212. retrieve results. 
  16213. The results parameter is the results record, which contains a handle to the
  16214. retrieved data. Results records are described in “Getting Query Results” earlier
  16215. in this chapter.
  16216.  
  16217. The timeout parameter specifies the value that he DBGetQueryResults uses for the
  16218. timeout parameter each time it calls the DBGetItem function. The timeout
  16219. parameter specifies the maximum amount of time that the database extension
  16220. should wait to receive results from the database server before canceling the
  16221. DBGetItem function. Specify the timeout parameter in sixtieths of a second. To
  16222. disable the timeout feature, set the timeout parameter to the value
  16223. kDBWaitForever. This parameter is ignored if you specify a nonzero value for the
  16224. asyncPB parameter.
  16225.  
  16226. You can use the statusProc pointer to specify a pointer to a status routine that
  16227. you provide. The DBGetQueryResults function calls your status routine after it
  16228. calls the DBGetItem function to retrieve a data item. When it calls the status
  16229. routine, the DBGetQueryResults function provides the results of the DBGetItem
  16230. function, the data type, the data length, number of decimal places, and flags
  16231. associated with the data item, and a pointer to the data item. Status routines
  16232. are discussed in “Writing a Status Routine For High-Level Functions” earlier in
  16233. this chapter.
  16234.  
  16235. If you specify a pointer to an asynchronous parameter block in the asyncPB
  16236. parameter, the DBGetQueryResults function calls the DBGetItem function
  16237. asynchronously for each data item. As soon as the DBGetItem function has started
  16238. execution, it returns control to your application. Your application must then
  16239. call the WaitNextEvent routine periodically to allow this asynchronous routine
  16240. to run, and it must check the result field of the asynchronous parameter block
  16241. to determine when the routine has completed execution.
  16242.  
  16243. Result codes
  16244. noErr                 0  Query execution successful; no results returned
  16245. userCanceledErr    –128  Function canceled by status routine
  16246. rcDBValue          –801  Data available 
  16247. rcDBError          –802  Query execution ended in an error
  16248. rcDBBreak          –805  Function timed out
  16249. rcDBExec           –806  Query currently executing 
  16250. rcDBBadSessID      –807  Session ID is invalid
  16251. rcDBAsyncNotSupp   –811  The database extension does not support 
  16252.                          asynchronous calls
  16253. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16254.  
  16255. FUNCTION DBResultsToText (results: ResultsRecord; VAR theText: Handle) : OSErr;
  16256.  
  16257. The DBResultsToText function calls result handlers to convert to text the data
  16258. retrieved by the DBGetQueryResults function. Result handlers are described in 
  16259. “Converting Query Results to Text” earlier in this chapter.
  16260.  
  16261. The results parameter is the results record returned by the DBGetQueryResults
  16262. function. The parameter theText contains a handle to the converted text. This
  16263. handle is allocated by the Database Access Manager.
  16264.  
  16265. Result code
  16266. noErr                 0  No error
  16267. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16268. _______________________________________________________________________________
  16269.  
  16270. æKY Low-Level…Interface
  16271. æC »Low-Level Interface                                            Database Access Manager
  16272. _______________________________________________________________________________
  16273.  
  16274. The low-level interface to the Database Access Manager enables applications to
  16275. open and close sessions with a remote database server, send and execute queries,
  16276. retrieve query results, and obtain information about any current session. 
  16277. _______________________________________________________________________________
  16278.  
  16279. æKY Controlling…the…Session
  16280. æC »Controlling the Session                                        Database Access Manager
  16281. _______________________________________________________________________________
  16282.  
  16283. The functions in this section initiate and close sessions, obtain information
  16284. about sessions, and cancel functions that were called asynchronously.
  16285.  
  16286. FUNCTION DBInit (VAR sessID: LongInt; ddevName: Str63; host, user, password,
  16287.                  connStr: Str255; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16288.  
  16289. The DBInit function initiates a session with a remote database server. You must
  16290. initiate a session before you call any Database Access Manager function that
  16291. requires a session ID as an input parameter. If the DBInit function returns a
  16292. nonzero session ID, you must call the DBEnd function to terminate the session,
  16293. even if the DBInit function also returns a result code other than noErr.
  16294.  
  16295. Because the high-level function DBStartQuery can call the DBInit function, if
  16296. you have called the DBStartQuery function, you do not have to call the DBInit
  16297. function. 
  16298.  
  16299. The DBInit function returns the session ID in the sessID parameter. This session
  16300. ID is unique; no other current session, for any database extension, has the same
  16301. session ID. You must specify the session ID any time you want to send data to or
  16302. retrieve data from this session. Depending on the database extension you are
  16303. using, the DBInit function might return a session ID of 0 if it fails to
  16304. initiate a session, or it might return a nonzero session ID and a result code
  16305. other than noErr. In the latter case, you can pass the session ID to the
  16306. DBGetErr function to determine the cause of the error.
  16307.  
  16308. The ddevName parameter is a string of no more than 63 characters that specifies
  16309. the name of the database extension. The name of the database extension is
  16310. contained in the database extension file in a resource of type 'STR ' with an ID
  16311. of 128. For the CL/1 database extension provided by Apple , for example, this
  16312. string is “CL/1”.
  16313.  
  16314. The host parameter specifies the name of the remote system on which the database
  16315. server is located. This name depends on the manner in which the database
  16316. extension establishes communication with the remote database server and on how
  16317. the system administrator has set up the computer system.
  16318.  
  16319. The user parameter specifies the name of the user, and the password parameter
  16320. specifies the password associated with the user name.
  16321.  
  16322. The connStr parameter is a connection string that is passed to the database
  16323. server, which might pass it on to the database management software on the remote
  16324. computer. This string is necessary in some systems to complete log-on
  16325. procedures. 
  16326. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16327. do not want to call the function asynchronously, set this parameter to NIL.
  16328.  
  16329. Result codes
  16330. noErr                 0  No error
  16331. rcDBError          –802  Error initiating session
  16332. rcDBBadDDev        –809  Couldn’t find specified database extension or 
  16333.                          trouble opening ddev file
  16334. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16335.                          database extension
  16336. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16337.  
  16338. FUNCTION DBEnd (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16339.  
  16340. The DBEnd function terminates a session with a remote database server and
  16341. terminates the network connection between the application and the remote
  16342. computer. You must call the DBEnd function to terminate a session.
  16343.  
  16344. The sessID parameter is the session ID that was returned by the DBInit function.
  16345.  
  16346. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16347. do not want to call the function asynchronously, set this parameter to NIL.
  16348.  
  16349. Result codes
  16350. noErr                 0  No error
  16351. rcDBError          –802  Error ending session
  16352. rcDBBadSessID      –807  Session ID is invalid
  16353. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16354.                          database extension
  16355. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16356.  
  16357. FUNCTION DBGetConnInfo (sessID: LongInt; sessNum: Integer; VAR returnedID,
  16358.                         version: LongInt; VAR ddevName: Str63; VAR host, user,
  16359.                         network, connStr: Str255; VAR start: LongInt; VAR state:
  16360.                         OSErr; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16361.  
  16362. The DBGetConnInfo function returns information about the specified session,
  16363. including 
  16364.  
  16365.   •   the version of the database extension
  16366.   •   the name of the remote system on which the session is running
  16367.   •   the user name
  16368.   •   the connection string that was used to establish communication
  16369.   •   the name of the network
  16370.   •   the time at which the session started, in ticks
  16371.   •   the status of the session
  16372.  
  16373. In addition, if you include a nonzero value for the sessID parameter when you
  16374. call the DBGetConnInfo function, the function returns the name of the database
  16375. extension. If you use 0 for the sessID parameter and specify the database
  16376. extension and session number instead, the function returns the session ID.
  16377.  
  16378. You can use this function to get information about a particular session, or you
  16379. can call the function repeatedly, incrementing the session number each time, to
  16380. get information about all of the sessions associated with a particular database
  16381. extension.
  16382.  
  16383. The sessID parameter is the session ID that was returned by the DBInit function.
  16384. The sessNum parameter is the session number of the session about which you want
  16385. information. You can specify either the session ID or the session number when
  16386. you call the DBInit function. If you specify the sessID parameter, use 0 for the
  16387. sessNum parameter. If you specify the sessNum parameter, then use 0 for the
  16388. sessID parameter. If you specify the sessNum parameter, you must specify a value
  16389. for the ddevName parameter as well. If you specify the session number and the
  16390. database extension, then the DBGetConnInfo function returns the session ID in
  16391. the returnedID parameter. 
  16392.  
  16393. The version parameter returns the version number of the database extension that
  16394. is the interface to the remote database server on which this session is running.
  16395.  
  16396. The ddevName parameter specifies the name of the database extension. If you
  16397. specify 0 for the session ID, you must include the name of the database
  16398. extension as well as a session number. If you specify a valid session ID, then
  16399. the DBGetConnInfo function returns the name of the database extension in the
  16400. ddevName parameter. The name of the database extension is included in a 'STR '
  16401. resource in the database extension file with a resource ID of 128.
  16402.  
  16403. The host, user, and connStr parameters are the host, user, and connection
  16404. strings that were used to establish communication with the remote database
  16405. server. The network parameter is the name of the network through which your
  16406. computer is communicating with the remote database server.
  16407.  
  16408. The start parameter is the time, in ticks, at which this session was initiated.
  16409.  
  16410. The state parameter returns one of the following values to provide information
  16411. about the status of the session:
  16412.  
  16413. CONST
  16414. noErr      =    0  ;No error; ready for more text
  16415. rcDBValue  = –801  ;Output data available
  16416. rcDBError  = –802  ;Execution ended in an error
  16417. rcDBExec   = –806  ;Busy; currently executing query
  16418.  
  16419. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16420. do not want to call the function asynchronously, set this parameter to NIL.
  16421.  
  16422. Result codes
  16423. noErr                 0  No error
  16424. rcDBBadSessNum     –808  Invalid session number
  16425. rcDBBadSessID      –807  Session ID is invalid or database extension name is 
  16426.                          invalid
  16427. rcDBBadDDev        –809  Couldn’t find specified database extension or 
  16428.                          trouble opening ddev file
  16429. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16430.                          database extension
  16431. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16432.  
  16433. FUNCTION DBGetSessionNum (sessID: LongInt; VAR sessNum: Integer; 
  16434.                           asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16435.  
  16436. The DBGetSessionNum function returns the session number of the session you
  16437. specify with the session ID parameter. The session number is unique for a
  16438. particular database extension, but the same session number might be in use for
  16439. different database extensions at the same time.
  16440.  
  16441. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16442. do not want to call the function asynchronously, set this parameter to NIL.
  16443.  
  16444. Result codes
  16445. noErr                 0  No error
  16446. rcDBBadSessID      –807  Session ID is invalid
  16447. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16448.                          database extension
  16449. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16450.  
  16451. FUNCTION DBKill (asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16452.  
  16453. The DBKill function cancels the execution of the asynchronous call specified by
  16454. the asyncPB parameter.
  16455.  
  16456. The asyncPB parameter is a pointer to the asynchronous parameter block.
  16457.  
  16458. Result codes
  16459. noErr                 0  Asynchronous routine canceled successfully
  16460. rcDBError          –802  Error canceling routine
  16461. rcDBBadAsynchPB    –812  Invalid parameter block specified
  16462. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16463. _______________________________________________________________________________
  16464.  
  16465. æKY Sending…and…Executing…Queries
  16466. æC »Sending and Executing Queries                                  Database Access Manager
  16467. _______________________________________________________________________________
  16468.  
  16469. The functions in this section send queries or portions of queries to the remote
  16470. database server, execute a query that has been sent, return information about
  16471. queries that have been sent, and halt execution of queries that are executing.
  16472.  
  16473. FUNCTION DBSend (sessID: LongInt; text: Ptr; len: Integer; asyncPB: 
  16474.                  DBAsyncParmBlkPtr) : OSErr;
  16475.  
  16476. The DBSend function sends a query or a portion of a query to the remote database
  16477. server. The database server appends this portion of the query to any portion you
  16478. sent previously. Because the Database Access Manager and database server do not
  16479. modify the string you send in any way, they do not insert any delimiter between
  16480. fragments of queries that you send to the database server. If you want a blank
  16481. or a semicolon to be included between query fragments, or if you want to use
  16482. return characters to divide the query into lines of text, you must include them
  16483. in the character string that you send with this function. 
  16484.  
  16485. The database server does not execute the query until you call the DBExec
  16486. function.
  16487.  
  16488. The sessID parameter is the session ID that was returned by the DBInit function.
  16489.  
  16490. The text parameter is a pointer to the query or query fragment that you want to
  16491. send to the database server. The query or query fragment must be a character
  16492. string. The len parameter specifies the length of the character string. If the
  16493. len parameter has a value of –1, then the character string is assumed to be 
  16494. “NULL terminated” (that is, the string ends with a NULL byte); otherwise, the
  16495. len parameter specifies the number of bytes in the string.
  16496.  
  16497. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16498. do not want to call the function asynchronously, set this parameter to NIL.
  16499.  
  16500. Result codes
  16501. noErr                 0  No error
  16502. rcDBError          –802  Error trying to send text
  16503. rcDBBadSessID      –807  Session ID is invalid
  16504. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16505.                          database extension
  16506. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16507.  
  16508. FUNCTION DBSendItem (sessID: LongInt; dataType: DBType; len, places, flags:
  16509.                      Integer; buffer: Ptr; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16510.  
  16511. The DBSendItem function sends a single data item to the remote database server.
  16512. You can use this function to send to the database server the data that you wish
  16513. to include in a query. The database extension or the database server (depending
  16514. on how the system is implemented) converts the data item to a character string
  16515. and appends it to the query, just as a query program fragment is appended to the
  16516. query by the DBSend function. The query is not executed until you call the
  16517. DBExec function.
  16518.  
  16519. The sessID parameter is the session ID that was returned by the DBInit function.
  16520.  
  16521. The dataType, len, and places parameters specify the data type, length, and
  16522. number of decimal places for the data item that you are sending to the remote
  16523. database server. The database extension and database server ignore the len
  16524. parameter if the data type has an implied length. The database extension and
  16525. database server ignore the places parameter for all values of the dataType
  16526. parameter except typeDecimal and typeMoney. Data types are discussed in “Getting
  16527. Query Results” earlier in this chapter.
  16528.  
  16529. The buffer parameter is a pointer to the memory location of the data item that
  16530. you want to send. When you use the DBSendItem function to send an item of data
  16531. to a database server, the database extension and database server format the data
  16532. according to the data type, length, and decimal places you specified, converts
  16533. it to a character string, and appends the data to the query. 
  16534.  
  16535. Set the flags parameter to 0. There are no flags currently defined for the
  16536. DBSendItem function. 
  16537.  
  16538. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16539. do not want to call the function asynchronously, set this parameter to NIL.
  16540.  
  16541. Result codes
  16542. noErr                 0  No error
  16543. rcDBError          –802  Error trying to send item
  16544. rcDBBadSessID      –807  Session ID is invalid
  16545. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16546.                          database extension
  16547. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16548.  
  16549. FUNCTION DBExec (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16550.  
  16551. The DBExec function initiates execution of a query that you have sent to the
  16552. remote database server. Use the DBSend and DBSendItem functions to send a query
  16553. to the database server. Use the DBState function to determine the status of a
  16554. query after you have initiated execution.
  16555.  
  16556. The sessID parameter is the session ID that was returned by the DBInit function.
  16557.  
  16558. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16559. do not want to call the function asynchronously, set this parameter to NIL.
  16560.  
  16561. Result codes
  16562. noErr                 0  Execution has begun
  16563. rcDBError          –802  Error trying to begin execution
  16564. rcDBBadSessID      –807  Session ID is invalid
  16565. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16566.                          database extension
  16567. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16568.  
  16569. FUNCTION DBState (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16570.  
  16571. The result code returned by the DBState function indicates the status of the
  16572. remote database server. You can use this function to determine whether the
  16573. database server has successfully executed a query and whether it has data
  16574. available for you to retrieve. 
  16575.  
  16576. The sessID parameter is the session ID that was returned by the DBInit function.
  16577.  
  16578. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16579. do not want to call the function asynchronously, set this parameter to NIL.
  16580.  
  16581. Result codes
  16582. noErr                 0  No error; ready for more text
  16583. rcDBValue          –801  Output data available
  16584. rcDBError          –802  Execution ended in an error
  16585. rcDBExec           –806  Currently executing query
  16586. rcDBBadSessID      –807  Session ID is invalid
  16587. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by
  16588.                          database extension
  16589. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16590.  
  16591. FUNCTION DBGetErr (sessID: LongInt; VAR err1,err2: LongInt; VAR item1, item2, 
  16592.                    errorMsg: Str255; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16593.  
  16594. The DBGetErr function retrieves error codes and error messages from a remote
  16595. database server. You can use this function to obtain information when a
  16596. low-level function returns the result code rcDBError. If the DBState function
  16597. returns the rcDBError result code, indicating that execution of a query ended in
  16598. an error, the error information can help you debug the query. The meaning of
  16599. each error code and error message returned by this function depends on the
  16600. database server with which you are communicating; see the documentation for that
  16601. database server for more information.
  16602.  
  16603. The sessID parameter is the session ID that was returned by the DBInit function.
  16604.  
  16605. The err1 and err2 parameters return the primary and secondary error codes. The
  16606. item1 and item2 parameters return strings that describe the objects of the error
  16607. message. The errorMsg parameter returns the error message.
  16608.  
  16609. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16610. do not want to call the function asynchronously, set this parameter to NIL.
  16611.  
  16612. Result codes
  16613. noErr                 0  No error
  16614. rcDBError          –802  Error retrieving error information
  16615. rcDBBadSessID      –807  Session ID is invalid
  16616. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by
  16617.                          database extension
  16618. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16619.  
  16620. FUNCTION DBBreak (sessID: LongInt; abort: Boolean; asyncPB: DBAsyncParmBlkPtr) :
  16621.                   OSErr;
  16622.  
  16623. The DBBreak function can halt execution of a query and reinitialize the remote
  16624. database server, or it can unconditionally terminate a session with a database
  16625. server. You can use this function to cancel a query if you determine that it is
  16626. taking too long to complete execution, for example.
  16627.  
  16628. The sessID parameter is the session ID that was returned by the DBInit function.
  16629.  
  16630. If the abort parameter is TRUE (nonzero), the database server halts any query
  16631. that is executing and terminates the current session. If the abort parameter is
  16632. FALSE (0), the database server halts any query that is executing and
  16633. reinitializes itself.
  16634.  
  16635. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16636. do not want to call the function asynchronously, set this parameter to NIL.
  16637.  
  16638. Result codes
  16639. noErr                 0  Execution has begun
  16640. rcDBError          –802  Break or abort attempt was unsuccessful
  16641. rcDBBadSessID      –807  Session ID is invalid
  16642. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16643.                          database extension
  16644. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16645. _______________________________________________________________________________
  16646.  
  16647. æKY Retrieving…Results
  16648. æC »Retrieving Results                                             Database Access Manager
  16649. _______________________________________________________________________________
  16650.  
  16651. The functions in this section allow you to retrieve a data item from the
  16652. database server, to obtain information about the next data item, and to retrieve
  16653. the same data item more than once.
  16654.  
  16655. FUNCTION DBGetItem (sessID: LongInt; timeout: LongInt; VAR dataType: DBType; VAR
  16656.                     len,places,flags: Integer; buffer: Ptr; asyncPB: 
  16657.                     DBAsyncParmBlkPtr) : OSErr;
  16658.  
  16659. The DBGetItem function retrieves the next data item from the database server.
  16660. You can also use this function to obtain information about the next data item
  16661. without retrieving the data. You can use the DBGetItem function after you have
  16662. executed a query and the DBState function has returned the result code
  16663. rcDBValue, indicating that data is available. You can repeat the DBGetItem
  16664. function as many times as is necessary to retrieve all of the data returned by
  16665. the database in response to a query.
  16666.  
  16667. The sessID parameter is the session ID that was returned by the DBInit function.
  16668.  
  16669. You can use the timeout parameter to specify the maximum amount of time that the
  16670. database extension should wait to receive results from the database server
  16671. before canceling the function. Specify the timeout parameter in sixtieths of a
  16672. second. To disable the timeout feature, set the timeout parameter to the value
  16673. kDBWaitForever. If the timeout period expires, the DBGetItem function returns
  16674. the result code rcDBBreak. The DBGetItem function ignores the timeout parameter
  16675. if you call the function asynchronously. 
  16676.  
  16677. One use for the timeout parameter is to call the DBGetItem function periodically
  16678. with a short value set for this parameter in order to return control to your
  16679. application while a query is executing. Your application can then retrieve the
  16680. next data item as soon as execution of the query is complete without having to
  16681. call the DBState function to determine when data is available.
  16682.  
  16683. You can set the dataType parameter to specify the data type that you expect the
  16684. next data item to be. If the item is not of the expected data type, the database
  16685. extension returns the rcDBBadType result code. If you want to retrieve the next
  16686. data item regardless of type, set the dataType parameter to the value
  16687. typeAnyType. To skip the next data item, set the dataType parameter to the value
  16688. typeDiscard. The database server sets the dataType parameter to the actual type
  16689. of the data item when it retrieves the data item or returns information about
  16690. the data item. Data types are discussed in “Getting Query Results” earlier in
  16691. this chapter.
  16692.  
  16693. Set the len parameter to the length of the data buffer pointed to by the buffer
  16694. parameter. If you use the DBGetItem function to obtain information only (by
  16695. setting the buffer parameter to NIL), then the database server ignores the len
  16696. parameter. The database server sets the len parameter to the actual length of
  16697. the data item when it retrieves the data item or returns information about the
  16698. data item.
  16699.  
  16700. The database server returns in the places parameter the number of decimal places
  16701. in data items of types typeMoney and typeDecimal. For all other data types, the
  16702. database server returns 0 for the places parameter.
  16703.  
  16704. The buffer parameter is a pointer to the location where you want the retrieved
  16705. data item to be stored. You must ensure that the location you specify contains
  16706. enough space for the data item that will be returned. To determine the data
  16707. type, length, and number of decimal places of the next data item without
  16708. retrieving it, specify NIL for the buffer parameter. 
  16709.  
  16710. If the flags parameter is set to kDBLastColFlag (that is, the least significant
  16711. bit is set to 1), the data item is in the last column of the row. 
  16712. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16713. do not want to call the function asynchronously, set this parameter to NIL.
  16714.  
  16715. Result codes
  16716. noErr                 0  No error; no next data item
  16717. rcDBNull           –800  The data item was NULL
  16718. rcDBValue          –801  A nonzero data item was successfully retrieved
  16719. rcDBError          –802  Execution ended in an error
  16720. rcDBBadType        –803  Next data item not of requested data type
  16721. rcDBBreak          –805  Timed out
  16722. rcDBBadSessID      –807  Session ID is invalid
  16723. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16724.                          database extension
  16725. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16726.  
  16727. FUNCTION DBUnGetItem (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  16728.  
  16729. The DBUnGetItem function reverses the effect of the last call to the DBGetItem
  16730. function, in the sense that the next time you call the DBGetItem function it
  16731. retrieves the same item a second time. It does not remove the just-retrieved
  16732. data item from the input buffer. The DBUnGetItem function can reverse the effect
  16733. of only one call to the DBGetItem function; you cannot use it to step back
  16734. through several previously retrieved data items. 
  16735.  
  16736. The sessID parameter is the session ID that was returned by the DBInit function.
  16737.  
  16738. The asyncPB parameter is a pointer to the asynchronous parameter block. If you
  16739. do not want to call the function asynchronously, set this parameter to NIL.
  16740.  
  16741. Result codes
  16742. noErr                 0  No error
  16743. rcDBError          –802  Error executing function
  16744. rcDBBadSessID      –807  Session ID is invalid
  16745. rcDBAsyncNotSupp   –811  Asynchronous calls are not supported by 
  16746.                          database extension
  16747. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16748.  
  16749. _______________________________________________________________________________
  16750.  
  16751. æKY Installing…and…Removing…Result…Handlers
  16752. æC »Installing and Removing Result Handlers                        Database Access Manager
  16753. _______________________________________________________________________________
  16754.  
  16755. The functions in this section install, remove, and return pointers to result
  16756. handlers. Result handlers are discussed in “Converting Query Results to Text”
  16757. earlier in this chapter.
  16758.  
  16759. FUNCTION DBInstallResultHandler (dataType: DBType; theHandler: ProcPtr; 
  16760.                                  isSysHandler: Boolean) : OSErr;
  16761.  
  16762. The DBInstallResultHandler function installs a result handler for the data type
  16763. specified by the dataType parameter. The result handler is then used by the
  16764. DBResultsToText function to convert data of the specified type into a character
  16765. string.
  16766.  
  16767. The parameter theHandler is a pointer to the result handler. The isSysHandler
  16768. parameter specifies whether the result handler is an application result
  16769. handler—to be used only when the DBResultsToText function is called by the
  16770. application that installed the result handler—or  a system result handler—to be
  16771. used by every application running on the system.
  16772.  
  16773. When you install an application result handler, it replaces any result handler
  16774. with the same name previously installed by that application. Similarly, when you
  16775. install a system result handler, it replaces any existing system result handler
  16776. with the same name. Before you temporarily replace an existing result handler,
  16777. use the DBGetResultHandler function to obtain a pointer to the present handler,
  16778. and save the present result handler in your application’s private storage. Then
  16779. you can reinstall the original result handler when you are finished using the
  16780. temporary one.
  16781.  
  16782. Because an application result handler is used in preference to a system result
  16783. handler if both are available, you can temporarily replace a system result
  16784. handler for purposes of your application by installing an application result
  16785. handler for the same data type. You can then use the DBRemoveResultHandler
  16786. function to remove the application result handler and return to using the system
  16787. result handler whenever you wish.
  16788.  
  16789. Result code
  16790. noErr                 0  No error
  16791. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16792.  
  16793. FUNCTION DBRemoveResultHandler (dataType: DBType) : OSErr;
  16794.  
  16795. The DBRemoveResultHandler function removes from memory the application result
  16796. handler for the data type that you specify with the dataType parameter. This
  16797. function cannot remove a system result handler. 
  16798.  
  16799. Result codes
  16800. noErr                 0  No error
  16801. rcDBNoHandler      –813  There is no handler for this data type installed 
  16802.                          for the current application
  16803. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16804.  
  16805. FUNCTION DBGetResultHandler (dataType: DBType; VAR theHandler: ProcPtr; 
  16806.                              isSysHandler: Boolean) : OSErr;
  16807.  
  16808. The DBGetResultHandler function returns a pointer to a result handler for the
  16809. data type specified with the dataType parameter. The pointer is returned in the
  16810. parameter theHandler.
  16811.  
  16812. If you set the isSysHandler parameter to FALSE (0), the function returns a
  16813. pointer to the current application result handler for the specified data type,
  16814. or it returns 0 if there is no application result handler for that data type. If
  16815. you set the isSysHandler parameter to TRUE (nonzero), the function returns a
  16816. pointer to the current system result handler for the specified data type, or it
  16817. returns 0 if there is no system result handler for that data type.
  16818.  
  16819. You can use this function to obtain a pointer to a result handler so that you
  16820. can use it to convert to text  an individual data item retrieved by the
  16821. DBGetItem function. The DBGetQueryResults function automatically converts to
  16822. text all of the data pointed to by the results record.
  16823.  
  16824. Result codes
  16825. noErr                 0  No error
  16826. rcDBNoHandler      –813  There is no handler for this data type installed
  16827. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  16828.  
  16829. _______________________________________________________________________________
  16830.  
  16831. æKY Summary…of…the…Database…Access…Manager
  16832. æC »SUMMARY OF THE DATABASE ACCESS MANAGER                         Database Access Manager
  16833. _______________________________________________________________________________
  16834.  
  16835.  
  16836.  
  16837. The following cards summarize the data types, constants, and routines for the
  16838. Database Access Manager.
  16839. _______________________________________________________________________________
  16840.  
  16841. æKY Database…Access…Manager…Constants
  16842. æC »Constants                                                      Database Access Manager
  16843. _______________________________________________________________________________
  16844.  
  16845. CONST {Data types}
  16846. typeAnyType  = 0;  {can be any data type} 
  16847. typeNone  = 'none';  {no more data expected}
  16848. typeBoolean  = 'bool';  {Boolean}
  16849. typeSMInt      = 'smin';  {short integer}
  16850. typeInteger    = 'int ';  {integer}
  16851. typeSMFloat    = 'smfl';  {short floating point}
  16852. typeFloat      = 'flot';  {floating point}
  16853. typeDate       = 'date';  {date}
  16854. typeTime       = 'time';  {time}
  16855. typeTimeStamp  = 'tims';  {date and time}
  16856. typeChar       = 'char';  {character}
  16857. typeDecimal    = 'decm';  {decimal number}
  16858. typeMoney      = 'mony';  {money value}
  16859. typeVChar      = 'vchr';  {variable character}
  16860. typeVBin       = 'vbin';  {variable binary}
  16861. typeLChar      = 'lchr';  {long character}
  16862. typeLBin       = 'lbin';  {long binary}
  16863. typeDiscard    = 'disc';  {discard next data item}
  16864. typeUnknown    = 'unkn';  {result handler for unknown data type}
  16865. typeColBreak   = 'cbrk';  {result handler for column break}
  16866. typeRowBreak   = 'rbrk';  {result handler for end of line}
  16867.  
  16868. {DBStartQuery status messages}
  16869.  
  16870. kDBUpdateWind         = 0;  {update windows}
  16871. kDBAboutToInit        = 1;  {about to call DBInit}
  16872. kDBInitComplete       = 2;  {DBInit has completed}
  16873. kDBSendComplete       = 3;  {DBSend has completed}
  16874. kDBExecComplete       = 4;  {DBExec has completed}
  16875. kDBStartQueryComplete = 5;  {DBStartQuery is about to complete}
  16876.  
  16877. {DBGetQueryResults status messages}
  16878.  
  16879. kDBGetItemComplete         = 6;  {DBGetItem has completed}
  16880. kDBGetItemEndOfRow         = 7;  {data item received was end of row}
  16881. kDBGetQueryResultsComplete = 8;  {DBGetQueryResults has completed}
  16882.  
  16883.  
  16884. kDBWaitForever  = -1;  {infinite timeout value for DBGetItem}
  16885.  
  16886. kAsyncSupported = $00000001;  {asynchronous execution supported}
  16887.  
  16888. kDBLastColFlag = $0001;  {data item is last column of the row}
  16889. _______________________________________________________________________________
  16890.  
  16891. æKY Database…Access…Manager…Data…Types
  16892. æC »Data Types                                                     Database Access Manager
  16893. _______________________________________________________________________________
  16894.  
  16895. TYPE DBType = OSType;  {data type}
  16896.  
  16897. DBAsyncParamBlockRec = 
  16898. RECORD
  16899.   completionProc:  ProcPtr;  {pointer to completion routine}
  16900.   result:    OSErr;    {result of call}
  16901.   userRef:   LongInt;  {reserved for use by application}
  16902.   ddevRef:   LongInt;  {reserved for use by ddev}
  16903.   reserved:  LongInt   {reserved for use by Database Access Mgr}
  16904. END;
  16905.  
  16906. QueryArray = ARRAY[0..255] OF Handle;
  16907. QueryListPtr = ^QueryArray;
  16908. QueryListHandle = ^QueryListPtr;
  16909.  
  16910. ResListElem = 
  16911. RECORD
  16912.   TheType:  ResType;  {resource type}
  16913.   id:       Integer   {resource ID}
  16914. END;
  16915.  
  16916. ResListArray = ARRAY[0..255] OF ResListElem;
  16917. ResListPtr = ^ResListArray;
  16918. ResListHandle = ^ResListPtr;
  16919.  
  16920. QueryRecord = 
  16921. Record
  16922.   version:     Integer;          {version number}
  16923.   id:          Integer;          {resource ID of 'qrsc'}
  16924.   queryProc:   Handle;           {handle to query def func}
  16925.   ddevName:    Str63;            {database extension name}
  16926.   host:        Str255;           {name of remote computer}
  16927.   user:        Str255;           {name of user}
  16928.   password:    Str255;           {user's password}
  16929.   connStr:     Str255;           {connection string}
  16930.   currQuery:   Integer;          {index to current query}
  16931.   numQueries:  Integer;          {number of queries}
  16932.   queryList:   QueryListHandle;  {handle to array of handles to queries}
  16933.   numRes:      Integer;          {number of resources}
  16934.   resList:     ResListHandle;    {handle to array of resource types and IDs}
  16935.   dataHandle:  Handle;           {handle to memory for query def func}
  16936.   refCon:      LongInt           {reserved for query def func}
  16937. END;
  16938.  
  16939. ResultsRecord = 
  16940. RECORD
  16941.   numRows:   Integer;  {number of rows of data}
  16942.   numCols:   Integer;  {number of columns per row}
  16943.   colTypes:  Handle;   {handle to array of data types}
  16944.   colData:   Handle;   {handle to data}
  16945.   colInfo:   Handle    {handle to array of DBColInfoRecord records}
  16946. END;
  16947.  
  16948. DBColInfoRecord = 
  16949. RECORD
  16950.   len:     Integer;  {length of data item}
  16951.   places:  Integer;  {places for decimal and money data items}
  16952.   flags:   Integer;  {flags for data item}
  16953. END;
  16954.  
  16955. DDEVParams = 
  16956. RECORD
  16957.   message:      Integer;            {routine selector}
  16958.   ddevStorage:  LongInt;            {storage for use by database extension}
  16959.   asyncPB:      DBAsyncParmBlkPtr;  {pointer to asynch parameter block}
  16960.   sessID:       LongInt;            {session ID}
  16961.   returnedID:   LongInt;            {session ID returned}
  16962.   version:      LongInt;            {version number}
  16963.   start:        LongInt;            {session start time}
  16964.   host:         StringPtr;          {name of remote system}
  16965.   user:         StringPtr;          {user name}
  16966.   password:     StringPtr;          {user password}
  16967.   connStr:      StringPtr;          {connection string}
  16968.   network:      StringPtr;          {name of the network}
  16969.   buffer:       Ptr;                {data buffer}
  16970.   err1:         LongInt;            {primary error code returned}
  16971.   err2:         LongInt;            {secondary error code  returned}
  16972.   item1:        StringPtr;          {pointer to object of error message}
  16973.   item2:        StringPtr;          {pointer to object of error message}
  16974.   errorMsg:     StringPtr;          {pointer to error message}
  16975.   timeout:      LongInt;            {timeout value for DBGetItem}
  16976.   dataType:     DBType;             {data type}
  16977.   sessNum:      Integer;            {session number}
  16978.   state:        Integer;            {status of the database server}
  16979.   len:          Integer;            {length of data}
  16980.   places:       Integer;            {decimal places in data item}
  16981.   flags:        Integer;            {flags}
  16982.   abort:        Boolean             {flag for DBBreak}
  16983. END;
  16984. _______________________________________________________________________________
  16985.  
  16986. æKY Database…Access…Manager…Routines…Summary
  16987. æC »Routines                                                       Database Access Manager
  16988. _______________________________________________________________________________
  16989.  
  16990. Initializing and Closing the Database Access Manager
  16991.  
  16992. FUNCTION InitDBPack   : OSErr;
  16993. FUNCTION QuitDBPack   : OSErr;
  16994.  
  16995. High-Level Interface: Handling Query Documents
  16996.  
  16997. FUNCTION DBGetNewQuery  (queryID: Integer; VAR query: QueryHandle) : OSErr;
  16998. FUNCTION DBDisposeQuery  (query: QueryHandle) : OSErr;
  16999. FUNCTION DBStartQuery  (VAR sessID: LongInt; query: QueryHandle; statusProc: 
  17000.                         ProcPtr; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17001.  
  17002. High-Level Interface: Handling Query Results
  17003.  
  17004. FUNCTION DBGetQueryResults  (sessID: LongInt; VAR results: ResultsRecord;
  17005.                              timeout: LongInt; statusProc: ProcPtr; asyncPB:
  17006.                              DBAsyncParmBlkPtr) : OSErr;
  17007. FUNCTION DBResultsToText  (results: ResultsRecord; VAR theText: Handle) : OSErr;
  17008.  
  17009. Low-Level Interface: Controlling the Session
  17010.  
  17011. FUNCTION DBInit  (VAR sessID: LongInt; ddevName: Str63; host, user,password,
  17012.                   connStr: Str255; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17013. FUNCTION DBEnd  (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17014. FUNCTION DBGetConnInfo  (sessID: LongInt; sessNum: Integer; VAR returnedID,
  17015.                          version: LongInt; VAR ddevName: Str63; VAR host,user,
  17016.                          network,connStr: Str255; VAR start: LongInt; VAR state:
  17017.                          OSErr; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17018. FUNCTION DBGetSessionNum  (sessID: LongInt; VAR sessNum: Integer; asyncPB:
  17019.                            DBAsyncParmBlkPtr) : OSErr;
  17020. FUNCTION DBKill  (asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17021.  
  17022. Low-Level Interface: Sending and Executing Queries
  17023.  
  17024. FUNCTION DBSend  (sessID: LongInt; text: Ptr; len: Integer; asyncPB: 
  17025.                   DBAsyncParmBlkPtr) : OSErr;
  17026. FUNCTION DBSendItem  (sessID: LongInt; dataType: DBType; len, places,flags:
  17027.                       Integer; buffer: Ptr; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17028. FUNCTION DBExec  (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) :
  17029.  
  17030.  OSErr;
  17031. FUNCTION DBState  (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) :
  17032.  
  17033.  OSErr;
  17034. FUNCTION DBGetErr  (sessID: LongInt; VAR err1,err2: LongInt; VAR item1,item2,
  17035.                     errorMsg: Str255; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17036. FUNCTION DBBreak  (sessID: LongInt; abort: Boolean; asyncPB: DBAsyncParmBlkPtr) 
  17037.                    : OSErr;
  17038.  
  17039. Low-Level Interface: Retrieving Results
  17040.  
  17041. FUNCTION DBGetItem  (sessID: LongInt; timeout: LongInt; VAR dataType: DBType;
  17042.                      VAR len,places,flags: Integer; buffer: Ptr; asyncPB: 
  17043.                      DBAsyncParmBlkPtr) : OSErr;
  17044. FUNCTION DBUnGetItem  (sessID: LongInt; asyncPB: DBAsyncParmBlkPtr) : OSErr;
  17045.  
  17046. Installing and Removing Result Handlers
  17047.  
  17048. FUNCTION DBInstallResultHandler (dataType: DBType; theHandler: ProcPtr;
  17049.                                  isSysHandler: Boolean) : OSErr;
  17050. FUNCTION DBRemoveResultHandler (dataType: DBType) : OSErr;
  17051. FUNCTION DBGetResultHandler (dataType: DBType; VAR theHandler: ProcPtr;
  17052.                              isSysHandler: Boolean) : OSErr;
  17053. _______________________________________________________________________________
  17054.  
  17055. æKY Database…Access…Manager…Result…Codes
  17056. æC »Result Codes                                                   Database Access Manager
  17057. _______________________________________________________________________________
  17058.  
  17059. noErr                 0  No error
  17060. userCanceledErr    –128  User canceled the query 
  17061. rcDBNull           –800  The data item was NULL
  17062. rcDBValue          –801  Data available or successfully retrieved
  17063. rcDBError          –802  Error executing function
  17064. rcDBBadType        –803  Next data item not of requested data type
  17065. rcDBBreak          –805  Function timed out
  17066. rcDBExec           –806  Query currently executing 
  17067. rcDBBadSessID      –807  Session ID is invalid
  17068. rcDBBadSessNum     –808  Invalid session number
  17069. rcDBBadDDev        –809  Couldn’t find the specified database extension, or
  17070.                          error occurred in opening database extension
  17071. rcDBAsyncNotSupp   –811  The database extension does not support 
  17072.                          asynchronous calls
  17073. rcDBBadAsynchPB    –812  Invalid parameter block specified
  17074. rcDBNoHandler      –813  There is no handler for this data type installed 
  17075.                          for the current application
  17076. rcDBWrongVersion   –814  Wrong version number
  17077. rcDBPackNotInited  –815  The InitDBPack function has not yet been called
  17078. _______________________________________________________________________________
  17079.  
  17080. æKY Assembly-Language…Information…for…Database…Access…Manager
  17081. æC »Assembly-Language Information                                  Database Access Manager
  17082. _______________________________________________________________________________
  17083.  
  17084. Constants
  17085.  
  17086. ;Data types
  17087.  
  17088. typeAnyType    EQU  0       ;can be any data type 
  17089. typeNone       EQU  'none'  ;no more data expected
  17090. typeBoolean    EQU  'bool'  ;Boolean
  17091. typeSMInt      EQU  'smin'  ;short integer
  17092. typeInteger    EQU  'int '  ;integer
  17093. typeSMFloat    EQU  'smfl'  ;short floating point
  17094. typeFloat      EQU  'flot'  ;floating point
  17095. typeDate       EQU  'date'  ;date
  17096. typeTime       EQU  'time'  ;time
  17097. typeTimeStamp  EQU  'tims'  ;date and time
  17098. typeChar       EQU  'char'  ;character
  17099. typeDecimal    EQU  'decm'  ;decimal number
  17100. typeMoney      EQU  'mony'  ;money value
  17101. typeVChar      EQU  'vchr'  ;variable character
  17102. typeVBin       EQU  'vbin'  ;variable binary
  17103. typeLChar      EQU  'lchr'  ;long character
  17104. typeLBin       EQU  'lbin'  ;long binary
  17105. typeDiscard    EQU  'disc'  ;discard next data item
  17106. typeUnknown    EQU  'unkn'  ;result handler for unknown data type
  17107. typeColBreak   EQU  'cbrk'  ;result handler for column break
  17108. typeRowBreak   EQU  'rbrk'  ;result handler for end of line messages for ddev
  17109.  
  17110. kDBInit           EQU  0    ;DBInit function
  17111. kDBEnd            EQU  1    ;DBEnd function
  17112. kDBGetConnInfo    EQU  2    ;DBGetConnInfo function
  17113. kDBGetSessionNum  EQU  3    ;DBGetSessionNum  function
  17114. kDBSend           EQU  4    ;DBSend function
  17115. kDBSendItem       EQU  5    ;DBSendItem function
  17116. kDBExec           EQU  6    ;DBExec function
  17117. kDBState          EQU  7    ;DBState function
  17118. kDBGetErr         EQU  8    ;DBGetErr function
  17119. kDBBreak          EQU  9    ;DBBreak function
  17120. kDBGetItem        EQU  10   ;DBGetItem function
  17121. kDBUnGetItem      EQU  11   ;DBUnGetItem function
  17122. kDBKill           EQU  12   ;DBKill function
  17123. kDBOpen           EQU  100  ;DBOpen function
  17124. kDBClose          EQU  101  ;DBClose function
  17125. kDBIdle           EQU  102  ;DBIdle function
  17126.  
  17127. ;DBStartQuery status messages
  17128.  
  17129. kDBUpdateWind     EQU 0   ;update windows
  17130. kDBAboutToInit    EQU 1   ;about to call DBInit
  17131. kDBInitComplete   EQU 2   ;DBInit has completed
  17132. kDBSendComplete   EQU 3   ;DBSend has completed
  17133. kDBExecComplete   EQU 4   ;DBExec has completed
  17134.  
  17135. ;DBGetQueryResults status messages
  17136.  
  17137. kDBGetItemComplete          EQU 6  ;DBGetItem has completed
  17138. kDBGetItemEndOfRow          EQU 7  ;data item received was end of row
  17139. kDBGetQueryResultsComplete  EQU 8  ;DBGetQueryResults has completed
  17140.  
  17141. ;Miscellaneous
  17142.  
  17143. kDBWaitForever  EQU  -1    ;infinite timeout value for DBGetItem
  17144. kDDEVName       EQU  128   ;ID of 'STR ' resource with ddev name
  17145. kDDEVID         EQU  128   ;ID of 'ddev' resource
  17146. kDDEVFlags      EQU  128   ;ID of 'dflg' resource
  17147. kAsyncSupported EQU  1     ;asynchronous execution supported
  17148. kDBLastColFlag  EQU  1     ;data item is last column of the row
  17149.  
  17150. Asynchronous Parameter Block Data Structure
  17151.  
  17152. completionProc   long   pointer to completion routine
  17153. result           word   result of call
  17154. userRef          long   for application’s use
  17155. ddevRef          long   for ddev’s use
  17156. reserved         long   for internal use
  17157.  
  17158. Data Structure for Resource List in Query Record
  17159.  
  17160. theType    long   resource type
  17161. id         word   resource ID
  17162.  
  17163. Query Record Data Structure
  17164.  
  17165. version     word        version
  17166. id          word        ID of 'qrsc' this came from
  17167. queryProc   long        handle to query def proc
  17168. ddevName    64 bytes    ddev name
  17169. host        256 bytes   host
  17170. user        256 bytes   user
  17171. password    256 bytes   other connection info
  17172. currQuery   word        current query
  17173. numQueries  word        number of queries in query list
  17174. queryList   long        handle to list of queries
  17175. numRes      word        number of resources in resource list
  17176. resList     long        handle to list of other resources
  17177. dataHandle  long        data used by query def proc
  17178. refCon      long        query’s reference value
  17179.  
  17180. Results Record Data Structure
  17181.  
  17182. numRows     word   number of rows in result
  17183. numCols     word   number of columns per row
  17184. colTypes    long   data type array
  17185. colData     long   actual results
  17186. colLens     long   length array
  17187.    
  17188. Trap Macros Requiring Routine Selectors
  17189.  
  17190. _Pack13
  17191.  
  17192. Selector  Routine
  17193. $0100    InitDBPack
  17194. $0002    QuitDBPack
  17195. $0E04    DBInit
  17196. $0406    DBEnd
  17197. $1708    DBGetConnInfo
  17198. $050A    DBGetSessionNum
  17199. $070C    DBSend
  17200. $0B0E    DBSendItem
  17201. $0410    DBExec
  17202. $0412    DBState
  17203. $0E14    DBGetErr
  17204. $0516    DBBreak
  17205. $1018    DBGetItem
  17206. $041A    DBUnGetItem
  17207. $021C    DBKill
  17208. $031E    DBGetNewQuery
  17209. $0220    DBDisposeQuery
  17210. $0822    DBStartQuery
  17211. $0824    DBGetQueryResults
  17212. $0426    DBResultsToText
  17213. $0528    DBInstallResultHandler
  17214. $022A    DBRemoveResultHandler
  17215. $052C    DBGetResultHandler
  17216.  
  17217. _______________________________________________________________________________
  17218.  
  17219.  
  17220. æKY DeferredTaskManager
  17221. æC 
  17222.  
  17223. THE DEFERRED TASK MANAGER
  17224. _______________________________________________________________________________
  17225.  
  17226. About…The…DeferredTaskManager…Chapter
  17227. About…the…Deferred…Task…Manager
  17228. Deferred…Task…Manager…Routine
  17229. Summary…of…the…Deferred…Task…Manager
  17230. _______________________________________________________________________________
  17231.  
  17232.  
  17233.  
  17234. æKY About…The…DeferredTaskManager…Chapter
  17235. æC »ABOUT THIS CHAPTER                                     DeferredTaskManager
  17236. _______________________________________________________________________________
  17237.  
  17238. This chapter describes the Deferred Task Manager, which provides improved interrupt
  17239. handling by allowing lengthy tasks to be deferred.
  17240.  
  17241. Reader’s guide:  Lengthy tasks are usually initiated by slot cards.  Hence you
  17242.                  normally need the information in this chapter only if your
  17243.                  program deals with slot card interrupts.
  17244.  
  17245. _______________________________________________________________________________
  17246.  
  17247.  
  17248. æKY About…the…Deferred…Task…Manager
  17249. æC »ABOUT THE DEFERRED TASK MANAGER                        DeferredTaskManager
  17250. _______________________________________________________________________________
  17251.  
  17252. The Deferred Task Manager provides a way to defer the execution of interrupt tasks
  17253. until interrupts have been reenabled (processor priority level 0).  It maintains a
  17254. deferred task queue; instead of performing a task immediately, you can place the
  17255. information describing the task into the queue by calling the DTInstall procedure. 
  17256. All system interrupt handlers check this queue just before returning.  If there are
  17257. tasks in the queue and interrupts are about to be reenabled, the tasks are removed
  17258. and then executed with all interrupts enabled.
  17259.  
  17260. While useful for all types of interrupt tasks, the Deferred Task Manager is especially
  17261. handy for slot interrupts.  Interrupts from NuBus slot devices are received and
  17262. decoded by the VIA2, a second Versatile Interface Adapter
  17263. (Rockwell 6522) chip on the Macintosh II.  The VIA2 generates level-2 interrupts and,
  17264. due to the way the VIA chip works, interrupts must be serviced before the processor
  17265. priority level can be lowered (otherwise, a system error will occur).  During this
  17266. period (which could be quite long depending on the slot device) other level-2 interrupts
  17267. such as those for sound, as well as all level-1 interrupts, are blocked.  By using
  17268. the Deferred Task Manager, the processing of slot interrupts can be deferred until
  17269. all the slots are scanned; just before returning, the slot interrupt handler dispatches
  17270. to any tasks in the deferred task queue.
  17271.  
  17272. The deferred task queue is a standard Macintosh Operating System queue, as described
  17273. in the Operating System Utilities chapter.  Each entry in the deferred task queue has
  17274. the following structure:
  17275.  
  17276. TYPE  DeferredTask = RECORD
  17277.                        qLink:       QElemPtr;  {next queue entry}
  17278.                        qType:       INTEGER;   {queue type}
  17279.                        dtFlags:     INTEGER;   {reserved}
  17280.                        dtAddr:      ProcPtr;   {pointer to task}
  17281.                        dtParm:      LONGINT;   {optional parameter}
  17282.                        dtReserved:  LONGINT    {reserved--should be 0}
  17283.                      END;
  17284.  
  17285. QLink points to the next entry in the queue, and qType indicates the queue type,
  17286. which must always be ORD(dtQType).
  17287.  
  17288. DTAddr contains a pointer to the task.  DTParm is useful only from assembly language.
  17289.  
  17290. Assembly-language note:  DTParm lets you pass an optional parameter
  17291.                          to be loaded into register A1 just before
  17292.                          the task is executed.
  17293.  
  17294. _______________________________________________________________________________
  17295.  
  17296.  
  17297. æKY Deferred…Task…Manager…Routine
  17298. æC »DEFERRED TASK MANAGER ROUTINES                        DeferredTaskManager
  17299. _______________________________________________________________________________
  17300.  
  17301. FUNCTION DTInstall (dtTaskPtr: QElemPtr) : OSErr;
  17302.  
  17303. Trap macro  _DTInstall
  17304. On entry    A0:  dtTaskPtr (pointer)
  17305. On exit     D0:  result code (word)
  17306.  
  17307. Note:  To reduce overhead at interrupt time, instead of executing
  17308.        the _DTInstall trap you can load the jump vector jDTInstall
  17309.        into an address register other than A0 and execute a JSR
  17310.        instruction using that register.
  17311.  
  17312. DTInstall adds the specified task to the deferred task queue.  Your application must
  17313. fill in all fields of the task except qLink.  DTInstall returns one of the result
  17314. codes listed below.
  17315.  
  17316. Result codes    noErr      No error
  17317.                 vTypErr    Invalid queue element
  17318.  
  17319. _______________________________________________________________________________
  17320.  
  17321.  
  17322. æKY Summary…of…the…Deferred…Task…Manager
  17323. æC »SUMMARY OF THE DEFERRED TASK MANAGER                   DeferredTaskManager
  17324. _______________________________________________________________________________
  17325.  
  17326. Data Types
  17327.  
  17328. TYPE
  17329.   DeferredTask = RECORD
  17330.                    qLink:       QElemPtr;  {next queue entry}
  17331.                    qType:       INTEGER;   {queue type}
  17332.                    dtFlags:     INTEGER;   {reserved}
  17333.                    dtAddr:      ProcPtr;   {pointer to task}
  17334.                    dtParm:      LONGINT;   {optional parameter}
  17335.                    dtReserved:  LONGINT    {reserved--should be 0}
  17336.                  END;
  17337.  
  17338. _______________________________________________________________________________
  17339.  
  17340. Routines
  17341.  
  17342. FUNCTION DTInstall (dtTaskPtr: QElemPtr) : OSErr;
  17343.  
  17344. _______________________________________________________________________________
  17345.  
  17346. Assembly-Language Information
  17347.  
  17348. Routines
  17349.  
  17350. Trap macro    On entry                On exit
  17351.  
  17352. _DTInstall    A0:  dtTaskPtr (ptr)    D0:  result code (word)
  17353.  
  17354. Structure of Deferred Task Manager Queue Entry
  17355.  
  17356. qLink      Pointer to next queue entry
  17357. qType      Queue type (word)
  17358. dtFlags    Reserved (word)
  17359. dtAddr     Address of task
  17360. dtParm     Optional parameter (long)
  17361. dtResrvd   Reserved—should be 0 (long)
  17362. dtQElSize  Size in bytes of queue element
  17363.  
  17364. Variables
  17365.  
  17366. DTQueue     Deferred task queue header (10 bytes)
  17367. JDTInstall  Jump vector for DTInstall routine
  17368.  
  17369.  
  17370. æKY DeskManager
  17371. æC 
  17372.  
  17373. THE DESK MANAGER
  17374. _______________________________________________________________________________
  17375.  
  17376. About…The…DeskManager…Chapter
  17377. About…the…Desk…Manager
  17378. Using…the…Desk…Manager
  17379. Desk…Manager…Routines
  17380. Writing…Your…Own…Desk…Accessories
  17381. Summary…of…the…Desk…Manager
  17382. _______________________________________________________________________________
  17383.  
  17384.  
  17385.  
  17386. æKY About…The…DeskManager…Chapter
  17387. æC »ABOUT THIS CHAPTER                                            DeskManager
  17388. _______________________________________________________________________________
  17389.  
  17390. This chapter describes the Desk Manager, the part of the Toolbox that supports the
  17391. use of desk accessories from an application; the Calculator, for example, is a standard
  17392. desk accessory available to any application. You’ll learn how to use the Desk Manager
  17393. routines and how to write your own accessories.
  17394.  
  17395. You should already be familiar with:
  17396.   •  the basic concepts behind the Resource Manager and QuickDraw
  17397.   •  the Toolbox Event Manager, the Window Manager, the Menu Manager,
  17398.      and the Dialog Manager
  17399.   •  device drivers, as discussed in the Device Manager chapter, if
  17400.      you want to write your own desk accessories
  17401.  
  17402. _______________________________________________________________________________
  17403.  
  17404.  
  17405. æKY About…the…Desk…Manager
  17406. æC »ABOUT THE DESK MANAGER                                        DeskManager
  17407. _______________________________________________________________________________
  17408.  
  17409. The Desk Manager enables your application to support desk accessories, which are
  17410. “mini-applications” that can be run at the same time as a Macintosh application.
  17411. There are a number of standard desk accessories, such as the Calculator shown in
  17412. Figure 1. You can also write your own desk accessories if you wish.
  17413.  
  17414. •••Refer to Figure 1.•••
  17415.  
  17416. Figure 1–The Calculator Desk Accessory
  17417.  
  17418. The Macintosh user opens desk accessories by choosing them from the standard Apple
  17419. menu (whose title is an apple symbol), which by convention is the first menu in the
  17420. menu bar. When a desk accessory is chosen from this menu, it’s usually displayed in a
  17421. window on the desktop, and that window becomes the active window (see Figure 2).
  17422.  
  17423. •••Refer to Figure 2.•••
  17424.  
  17425. Figure 2–Opening a Desk Accessory
  17426.  
  17427. After being opened, the accessory may be used as long as it’s active. The user can
  17428. activate other windows and then reactivate the desk accessory by clicking inside it.
  17429. Whenever a standard desk accessory is active, it has a close box in its title bar.
  17430. Clicking the close box (or choosing Close from the File menu) makes the accessory
  17431. disappear, and the window that’s then frontmost becomes active.
  17432.  
  17433. •••Refer to Technical Note #5:•••
  17434.  
  17435. The window associated with a desk accessory is usually a rounded-corner window
  17436. (as shown in Figure 1) or a standard document window, although it can be any type of
  17437. window. It may even look and behave like a dialog window; the accessory can call on
  17438. the Dialog Manager to create the window and then use Dialog Manager routines to
  17439. operate on it. In any case, the window will be a system window, as indicated by the
  17440. fact that its windowKind field contains a negative value.
  17441.  
  17442. The Desk Manager provides a mechanism that lets standard commands chosen from the
  17443. Edit menu be applied to a desk accessory when it’s active. Even if the commands
  17444. aren’t particularly useful for editing within the accessory, they may be useful for
  17445. cutting and pasting between the accessory and the application or even another accessory.
  17446. For example, the result of a calculation made with the Calculator can be copied and
  17447. pasted into a document prepared in MacWrite.
  17448.  
  17449. A desk accessory may also have its own menu. When the accessory becomes active, the
  17450. title of its menu is added to the menu bar and menu items may be chosen from it. Any
  17451. of the application’s menus or menu items that no longer apply are disabled. A desk
  17452. accessory can even have an entire menu bar full of its own menus, which will completely
  17453. replace the menus already in the menu bar. When an accessory that has its own menu or
  17454. menus becomes inactive, the menu bar is restored to normal.
  17455.  
  17456. Although desk accessories are usually displayed in windows (one per accessory); it’s
  17457. possible for an accessory to have only a menu (or menus) and not a window. In this
  17458. case, the menu includes a command to close the accessory. Also, a desk accessory
  17459. that’s displayed in a window may create any number of additional windows while it’s
  17460. open.
  17461.  
  17462. A desk accessory is actually a special type of device driver—special in that it may
  17463. have its own windows and menus for interacting with the user. The value in the windowKind
  17464. field of a desk accessory’s window is a reference number that uniquely identifies the
  17465. driver, returned by the Device Manager when the driver was opened. Desk accessories
  17466. and other RAM drivers used by Macintosh applications are stored in resource files.
  17467.  
  17468. _______________________________________________________________________________
  17469.  
  17470.  
  17471. æKY Using…the…Desk…Manager
  17472. æC »USING THE DESK MANAGER                                        DeskManager
  17473. _______________________________________________________________________________
  17474.  
  17475. To allow access to desk accessories, your application must do the following:
  17476.  
  17477.   •  Initialize TextEdit and the Dialog Manager, in case any desk
  17478.      accessories are displayed in windows created by the Dialog Manager
  17479.      (which uses TextEdit).
  17480.   •  Set up the Apple menu as the first menu in the menu bar. You can put
  17481.      the names of all currently available desk accessories in a menu by
  17482.      using the Menu Manager procedure AddResMenu.
  17483.   •  Set up an Edit menu that includes the standard commands Undo, Cut,
  17484.      Copy, Paste, and Clear (in that order, with a dividing line between
  17485.      Undo and Cut), even if your application itself doesn’t support any
  17486.      of these commands.
  17487.  
  17488. Note:  Applications should leave enough space in the menu bar for a
  17489.        desk accessory’s menu to be added.
  17490.  
  17491. When the user chooses a desk accessory from the Apple menu, call the Menu Manager
  17492. procedure GetItem to get the name of the desk accessory, and then the Desk Manager
  17493. function OpenDeskAcc to open and display the accessory. When a system window is
  17494. active and the user chooses Close from the File menu, close the desk accessory with
  17495. the CloseDeskAcc procedure.
  17496.  
  17497. Warning:  Most open desk accessories allocate nonrelocatable objects
  17498.           (such as windows) in the heap, resulting in fragmentation of
  17499.           heap space. Before beginning an operation that requires a large
  17500.           amount of memory, your application may want to close all open
  17501.           desk accessories (or allow the user to close some of them).
  17502.  
  17503. When the Toolbox Event Manager function GetNextEvent reports that a mouse-down event
  17504. has occurred, your application should call the Window Manager function FindWindow to
  17505. find out where the mouse button was pressed. If FindWindow returns the predefined
  17506. constant inSysWindow, which means that the mouse button was pressed in a system
  17507. window, call the Desk Manager procedure SystemClick. SystemClick handles mouse-down
  17508. events in system windows, routing them to desk accessories where appropriate.
  17509.  
  17510. Note:  The application needn’t be concerned with exactly which desk
  17511.        accessories are currently open.
  17512.  
  17513. When the active window changes from an application window to a system window, the
  17514. application should disable any of its menus or menu items that don’t apply while an
  17515. accessory is active, and it should enable the standard editing commands Undo, Cut,
  17516. Copy, Paste, and Clear, in the Edit menu. An application should disable any editing
  17517. commands it doesn’t support when one of its own windows becomes active.
  17518.  
  17519. When a mouse-down event occurs in the menu bar, and the application determines that
  17520. one of the five standard editing commands has been invoked, it should call SystemEdit.
  17521. Only if SystemEdit returns FALSE should the application process the editing command
  17522. itself; if the active window belongs to a desk accessory, SystemEdit passes the
  17523. editing command on to that accessory and returns TRUE.
  17524.  
  17525. Keyboard equivalents of the standard editing commands are passed on to desk accessories
  17526. by the Desk Manager, not by your application.
  17527.  
  17528. Warning:  The standard keyboard equivalents for the commands in the Edit
  17529.           menu must not be changed or assigned to other commands; the Desk
  17530.           Manager automatically interprets Command-Z, X, C, and V as Undo,
  17531.           Cut, Copy, and Paste, respectively.
  17532.  
  17533. Certain periodic actions may be defined for desk accessories. To see that
  17534. they’re performed, you need to call the SystemTask procedure at least once every time
  17535. through your main event loop.
  17536.  
  17537. The two remaining Desk Manager routines—SystemEvent and SystemMenu—are never called
  17538. by the application, but are described in this chapter because they reveal inner
  17539. mechanisms of the Toolbox that may be of interest to advanced programmers.
  17540.  
  17541. _______________________________________________________________________________
  17542.  
  17543.  
  17544. æKY Desk…Manager…Routines
  17545. æC »DESK MANAGER ROUTINES                                          DeskManager
  17546. _______________________________________________________________________________
  17547.  
  17548. »Opening and Closing Desk Accessories
  17549.  
  17550. FUNCTION OpenDeskAcc (theAcc:  Str255) :  INTEGER;
  17551.  
  17552. OpenDeskAcc opens the desk accessory having the given name and displays its window
  17553. (if any) as the active window. The name is the accessory’s resource name, which you
  17554. get from the Apple menu by calling the Menu Manager procedure GetItem. OpenDeskAcc
  17555. calls the Resource Manager to read the desk accessory from the resource file into the
  17556. application heap.
  17557.  
  17558. You should ignore the value returned by OpenDeskAcc. If the desk accessory is successfully
  17559. opened, the function result is its driver reference number. However, if the desk
  17560. accessory can’t be opened, the function result is undefined; the accessory will have
  17561. taken care of informing the user of the problem (such as memory full) and won’t
  17562. display itself.
  17563.  
  17564. Warning:  Early versions of some desk accessories may set the current
  17565.           grafPort to the accessory’s port upon return from OpenDeskAcc.
  17566.           To be safe, you should bracket your call to OpenDeskAcc with
  17567.           calls to the QuickDraw procedures GetPort and SetPort, to save
  17568.           and restore the current port.
  17569.  
  17570. Note:  Programmers concerned about the amount of available memory should
  17571.        be aware that an open desk accessory uses from 1K to 3K bytes of
  17572.        heap space in addition to the space needed for the accessory itself.
  17573.        The desk accessory is responsible for determining whether there is
  17574.        sufficient memory for it to run; this can be done by calling
  17575.        SizeResource followed by ResrvMem.
  17576.  
  17577. PROCEDURE CloseDeskAcc (refNum:  INTEGER);
  17578.  
  17579. When a system window is active and the user chooses Close from the File menu, call
  17580. CloseDeskAcc to close the desk accessory. RefNum is the driver reference number for
  17581. the desk accessory, which you get from the windowKind field of its window.
  17582.  
  17583. The Desk Manager automatically closes a desk accessory if the user clicks its close
  17584. box. Also, since the application heap is released when the application terminates,
  17585. every desk accessory goes away at that time.
  17586.  
  17587. _______________________________________________________________________________
  17588.  
  17589. »Handling Events in Desk Accessories
  17590.  
  17591. PROCEDURE SystemClick (theEvent:  EventRecord; theWindow:  WindowPtr);
  17592.  
  17593. When a mouse-down event occurs and the Window Manager function FindWindow reports
  17594. that the mouse button was pressed in a system window, the application should call
  17595. SystemClick with the event record and the window pointer. If the given window belongs
  17596. to a desk accessory, SystemClick sees that the event gets handled properly.
  17597.  
  17598. SystemClick determines which part of the desk accessory’s window the mouse button was
  17599. pressed in, and responds accordingly (similar to the way your application responds to
  17600. mouse activities in its own windows).
  17601.  
  17602.   •  If the mouse button was pressed in the content region of the window
  17603.      and the window was active, SystemClick sends the mouse-down event to
  17604.      the desk accessory, which processes it as appropriate.
  17605.   •  If the mouse button was pressed in the content region and the window
  17606.      was inactive, SystemClick makes it the active window.
  17607.   •  If the mouse button was pressed in the drag region, SystemClick calls
  17608.      the Window Manager procedure DragWindow to pull an outline of the window
  17609.      across the screen and move the window to a new location. If the window
  17610.      was inactive, DragWindow also makes it the active window (unless the
  17611.      Command key was pressed along with the mouse button).
  17612.   •  If the mouse button was pressed in the go-away region, SystemClick calls
  17613.      the Window Manager function TrackGoAway to determine whether the mouse
  17614.      is still inside the go-away region when the click is completed:  If
  17615.      so, it tells the desk accessory to close itself; otherwise, it does
  17616.      nothing.
  17617.  
  17618. FUNCTION SystemEdit (editCmd:  INTEGER) :  BOOLEAN;
  17619.  
  17620. Assembly-language note:  The macro you invoke to call SystemEdit from
  17621.                          assembly language is named _SysEdit.
  17622.  
  17623. Call SystemEdit when there’s a mouse-down event in the menu bar and the user chooses
  17624. one of the five standard editing commands from the Edit menu. Pass one of the following
  17625. as the value of the editCmd parameter:
  17626.  
  17627.   editCmd    Editing command
  17628.  
  17629.     0            Undo
  17630.     2            Cut
  17631.     3            Copy
  17632.     4            Paste
  17633.     5            Clear
  17634.  
  17635. If your Edit menu contains these five commands in the standard arrangement (the order
  17636. listed above, with a dividing line between Undo and Cut), you can simply call
  17637.  
  17638.   SystemEdit(menuItem-1)
  17639.  
  17640. where menuItem is the menu item number.
  17641.  
  17642. If the active window doesn’t belong to a desk accessory, SystemEdit returns FALSE;
  17643. the application should then process the editing command as usual. If the active
  17644. window does belong to a desk accessory, SystemEdit asks that accessory to process the
  17645. command and returns TRUE; in this case, the application should ignore the command.
  17646.  
  17647. Note:  It’s up to the application to make sure desk accessories get
  17648.        their editing commands that are chosen from the Edit menu. In
  17649.        particular, make sure your application hasn’t disabled the Edit
  17650.        menu or any of the five standard commands when a desk accessory
  17651.        is activated.
  17652.  
  17653. _______________________________________________________________________________
  17654.  
  17655. »Performing Periodic Actions
  17656.  
  17657. PROCEDURE SystemTask;
  17658.  
  17659. For each open desk accessory (or other device driver performing periodic actions),
  17660. SystemTask causes the accessory to perform the periodic action defined for it, if any
  17661. such action has been defined and if the proper time period has passed since the
  17662. action was last performed. For example, a clock accessory can be defined such that
  17663. the second hand is to move once every second; the periodic action for the accessory
  17664. will be to move the second hand to the next position, and SystemTask will alert the
  17665. accessory every second to perform that action.
  17666.  
  17667. You should call SystemTask as often as possible, usually once every time through your
  17668. main event loop. Call it more than once if your application does an unusually large
  17669. amount of processing each time through the loop.
  17670.  
  17671. Note:  SystemTask should be called at least every sixtieth of a second.
  17672.  
  17673. _______________________________________________________________________________
  17674.  
  17675. »Advanced Routines
  17676.  
  17677. FUNCTION SystemEvent (theEvent:  EventRecord) :  BOOLEAN;
  17678.  
  17679. SystemEvent is called only by the Toolbox Event Manager function GetNextEvent when it
  17680. receives an event, to determine whether the event should be handled by the application
  17681. or by the system. If the given event should be handled by the application, SystemEvent
  17682. returns FALSE; otherwise, it calls the appropriate system code to handle the event
  17683. and returns TRUE.
  17684.  
  17685. In the case of a null or mouse-down event, SystemEvent does nothing but return FALSE.
  17686. Notice that it responds this way to a mouse-down event even though the event may in
  17687. fact have occurred in a system window (and therefore may have to be handled by the
  17688. system). The reason for this is that the check for exactly where the event occurred
  17689. (via the Window Manager function FindWindow) is made later by the application and so
  17690. would be made twice if SystemEvent were also to do it. To avoid this duplication,
  17691. SystemEvent passes the event on to the application and lets it make the sole call to
  17692. FindWindow. Should FindWindow reveal that the mouse-down event did occur in a system
  17693. window, the application can then call SystemClick, as described above, to get the
  17694. system to handle it.
  17695.  
  17696. If the given event is a mouse-up or any keyboard event (including keyboard equivalents
  17697. of commands), SystemEvent checks whether the active window belongs to a desk accessory
  17698. and whether that accessory can handle this type of event. If so, it sends the event
  17699. to the desk accessory and returns TRUE; otherwise, it returns FALSE.
  17700.  
  17701. If SystemEvent is passed an activate or update event, it checks whether the window
  17702. the event occurred in is a system window belonging to a desk accessory and whether
  17703. that accessory can handle this type of event. If so, it sends the event to the desk
  17704. accessory and returns TRUE; otherwise, it returns FALSE.
  17705.  
  17706. Note:  It’s unlikely that a desk accessory would not be set up to handle
  17707.        keyboard, activate, and update events, or that it would handle
  17708.        mouse-up events.
  17709.  
  17710.        If the given event is a disk-inserted event, SystemEvent does some
  17711.        low-level processing (by calling the File Manager function MountVol)
  17712.        but passes the event on to the application by returning FALSE, in
  17713.        case the application wants to do further processing. Finally,
  17714.        SystemEvent returns FALSE for network, device driver, and
  17715.        application-defined events.
  17716.  
  17717. Assembly-language note:  Advanced programmers can make SystemEvent
  17718.                          always return FALSE by setting the global
  17719.                          variable SEvtEnb (a byte) to 0.
  17720.  
  17721. PROCEDURE SystemMenu (menuResult:  LONGINT);
  17722.  
  17723. SystemMenu is called only by the Menu Manager functions MenuSelect and MenuKey, when
  17724. an item in a menu belonging to a desk accessory has been chosen. The menuResult
  17725. parameter has the same format as the value returned by MenuSelect and MenuKey:  the
  17726. menu ID in the high-order word and the menu item number in the low-order word. (The
  17727. menu ID will be negative.) SystemMenu directs the desk accessory to perform the
  17728. appropriate action for the given menu item.
  17729.  
  17730. _______________________________________________________________________________
  17731.  
  17732.  
  17733. æKY Writing…Your…Own…Desk…Accessories
  17734. æC »WRITING YOUR OWN DESK ACCESSORIES                              DeskManager
  17735. _______________________________________________________________________________
  17736.  
  17737. To write your own desk accessory, you must create it as a device driver and include
  17738. it in a resource file, as described in the Device Manager chapter. Standard or shared
  17739. desk accessories are stored in the system resource file. Accessories specific to an
  17740. application are rare; if there are any, they’re stored in the application’s resource
  17741. file.
  17742.  
  17743. The resource type for a device driver is 'DRVR'. The resource ID for a desk accessory
  17744. is the driver’s unit number and must be between 12 and 31 inclusive.
  17745.  
  17746. Note:  A desk accessory will often have additional resources (such as
  17747.        pattern and string resources) that are associated with it. These
  17748.        resources must observe a special numbering convention, as described
  17749.        in the Resource Manager chapter.
  17750.  
  17751. The resource name should be whatever you want to appear in the Apple menu, but should
  17752. also include a nonprinting character; by convention, the name should begin with a NUL
  17753. character (ASCII code 0). The nonprinting character is needed to avoid conflict with
  17754. file names that are the same as the names of desk accessories.
  17755.  
  17756. Device drivers are usually written in assembly language. The structure of a device
  17757. driver is described in the Device Manager chapter. The rest of this section reviews
  17758. some of that information and presents additional details pertaining specifically to
  17759. device drivers that are desk accessories.
  17760.  
  17761. As shown in Figure 3, a device driver begins with a few words of flags and other
  17762. data, followed by offsets to the routines that do the work of the driver, an optional
  17763. title, and finally the routines themselves.
  17764.  
  17765. •••Refer to Figure 3.•••
  17766.  
  17767. Figure 3–Desk Accessory Device Driver
  17768.  
  17769. One bit in the high-order byte of the drvrFlags word is frequently used by desk
  17770. accessories:
  17771.  
  17772.   dNeedTime    .EQU    5    ; set if driver needs time for performing
  17773.                             ; a periodic action
  17774.  
  17775. Desk accessories may need to perform predefined actions periodically. For example, a
  17776. clock desk accessory may want to change the time it displays every second. If the
  17777. dNeedTime flag is set, the desk accessory does need to perform a periodic action, and
  17778. the drvrDelay word contains a tick count indicating how often the periodic action
  17779. should occur. Whether the action actually occurs as frequently as specified depends
  17780. on how often the application calls the Desk Manager procedure SystemTask. SystemTask
  17781. calls the desk accessory’s control routine (if the time indicated by drvrDelay has
  17782. elapsed), and the control routine must perform whatever predefined action is desired.
  17783.  
  17784. Note:  A desk accessory cannot rely on SystemTask being called regularly
  17785.        or frequently by an application. If it needs precise timing it
  17786.        should install a task to be executed during the vertical retrace
  17787.        interrupt. There are, however, certain restrictions on tasks
  17788.        performed during interrupts, such as not being able to make calls
  17789.        to the Memory Manager. For more information on these restrictions,
  17790.        see the Vertical Retrace Manager chapter. Periodic actions performed
  17791.        in response to SystemTask calls are not performed via an interrupt
  17792.        and so don’t have these restrictions.
  17793.  
  17794. The drvrEMask word contains an event mask specifying which events the desk accessory
  17795. can handle. If the accessory has a window, the mask should include keyboard, activate,
  17796. update, and mouse-down events, but must not include mouse-up events.
  17797.  
  17798. Note:  The accessory may not be interested in keyboard input, but it
  17799.        should still respond to key-down and auto-key events, at least
  17800.        with a beep.
  17801.  
  17802. When an event occurs, the Toolbox Event Manager calls SystemEvent. SystemEvent checks
  17803. the drvrEMask word to determine whether the desk accessory can handle the type of
  17804. event, and if so, calls the desk accessory’s control routine. The control routine
  17805. must perform whatever action is desired.
  17806.  
  17807. If the desk accessory has its own menu (or menus), the drvrMenu word contains the
  17808. menu ID of the menu (or of any one of the menus); otherwise, it contains 0. The menu
  17809. ID for a desk accessory menu must be negative, and it must be different from the menu
  17810. ID stored in other desk accessories.
  17811.  
  17812. Following these four words are the offsets to the driver routines and, optionally, a
  17813. title for the desk accessory (preceded by its length in bytes). You can use the title
  17814. in the driver as the title of the accessory’s window, or just as a way of identifying
  17815. the driver in memory.
  17816.  
  17817. Note:  A practical size limit for desk accessories is about 8K bytes.
  17818.  
  17819. _______________________________________________________________________________
  17820.  
  17821. »The Driver Routines
  17822.  
  17823. Of the five possible driver routines, only three need to exist for desk accessories:  the
  17824. open, close, and control routines. The other routines (prime and status) may be used
  17825. if desired for a particular accessory.
  17826. The open routine opens the desk accessory:
  17827.  
  17828.   •  It creates the window to be displayed when the accessory is opened,
  17829.      if any, specifying that it be invisible (since OpenDeskAcc will
  17830.      display it). The window can be created with the Dialog Manager
  17831.      function GetNewDialog (or NewDialog) if desired; the accessory
  17832.      will look and respond like a dialog box, and subsequent operations
  17833.      may be performed on it with Dialog Manager routines. In any case,
  17834.      the open routine sets the windowKind field of the window record to
  17835.      the driver reference number for the desk accessory, which it gets
  17836.      from the device control entry. (The reference number will be negative.)
  17837.      It also stores the window pointer in the device control entry.
  17838.   •  If the driver has any private storage, it allocates the storage,
  17839.      stores a handle to it in the device control entry, and initializes
  17840.      any local variables. It might, for example, create a menu or menus
  17841.      for the accessory.
  17842.  
  17843. If the open routine is unable to complete all of the above tasks (if it runs out of
  17844. memory, for example), it must do the following:
  17845.  
  17846.   •  Open only the minimum of data structures needed to run the desk accessory.
  17847.   •  Modify the code of every routine (except the close routine) so that
  17848.      the routine just returns (or beeps) when called.
  17849.   •  Modify the code of the close routine so that it disposes of only the
  17850.      minimum data structures that were opened.
  17851.   •  Display an alert indicating failure, such as “The Note Pad is not
  17852.      available”.
  17853.  
  17854. The close routine closes the desk accessory, disposing of its window (if any) and all
  17855. the data structures associated with it and replacing the window pointer in the device
  17856. control entry with NIL. If the driver has any private storage, the close routine also
  17857. disposes of that storage.
  17858.  
  17859. Warning:  A driver’s private storage shouldn’t be in the system heap,
  17860.           because the application heap is reinitialized when an application
  17861.           terminates, and the driver is lost before it can dispose of its
  17862.           storage.
  17863.  
  17864. The action taken by the control routine depends on information passed in the parameter
  17865. block pointed to by register A0. A message is passed in the csCode parameter; this
  17866. message is simply a number that tells the routine what action to take. There are nine
  17867. such messages:
  17868.  
  17869.   accEvent   .EQU    64    ;handle a given event
  17870.   accRun     .EQU    65    ;take the periodic action, if any,
  17871.                            ; for this desk accessory
  17872.   accCursor  .EQU    66    ;change cursor shape if appropriate; generate
  17873.                            ; null event if window was created by Dialog Manager
  17874.   accMenu    .EQU    67    ;handle a given menu item
  17875.   accUndo    .EQU    68    ;handle the Undo command
  17876.   accCut     .EQU    70    ;handle the Cut command
  17877.   accCopy    .EQU    71    ;handle the Copy command
  17878.   accPaste   .EQU    72    ;handle the Paste command
  17879.   accClear   .EQU    73    ;handle the Clear command
  17880.  
  17881. Note:  As described in the Device Manager chapter, the control routine
  17882.        may also receive the message goodBye in the csCode parameter telling
  17883.        it when the heap is about to be reinitialized.
  17884.  
  17885. Along with the accEvent message, the control routine receives in the csParam field a
  17886. pointer to an event record. The control routine must respond by handling the given
  17887. event in whatever way is appropriate for this desk accessory. SystemClick and SystemEvent
  17888. call the control routine with this message to send the driver an event that it should
  17889. handle—for example, an activate event that makes the desk accessory active or inactive.
  17890. When a desk accessory becomes active, its control routine might install a menu in the
  17891. menu bar. If the accessory becoming active has more than one menu, the control routine
  17892. should respond as follows:
  17893.  
  17894.   •  Store the accessory’s unique menu ID in the global variable
  17895.      MBarEnable. (This is the negative menu ID in the device driver
  17896.      and the device control entry.)
  17897.   •  Call the Menu Manager routines GetMenuBar to save the current
  17898.      menu list and ClearMenuBar to clear the menu bar.
  17899.   •  Install the accessory’s own menus in the menu bar.
  17900.  
  17901. Then, when the desk accessory becomes inactive, the control routine should call
  17902. SetMenuBar to restore the former menu list, call DrawMenuBar to draw the menu bar,
  17903. and set MBarEnable to 0.
  17904.  
  17905. The accRun message tells the control routine to perform the periodic action for this
  17906. desk accessory. For every open driver that has the dNeedTime flag set, the SystemTask
  17907. procedure calls the control routine with this message if the proper time period has
  17908. passed since the action was last performed.
  17909.  
  17910. The accCursor message makes it possible to change the shape of the cursor when it’s
  17911. inside an active desk accessory. SystemTask calls the control routine with this
  17912. message as long as the desk accessory is active. The control routine should respond
  17913. by checking whether the mouse location is in the desk
  17914. accessory’s window; if it is, it should set it to the standard arrow cursor (by
  17915. calling the QuickDraw procedure InitCursor), just in case the application has changed
  17916. the cursor and failed to reset it. Or, if desired, your accessory may give the cursor
  17917. a special shape (by calling the QuickDraw procedure SetCursor).
  17918.  
  17919. If the desk accessory is displayed in a window created by the Dialog Manager, the
  17920. control routine should respond to the accCursor message by generating a null event
  17921. (storing the event code for a null event in an event record) and passing it to DialogSelect.
  17922. This enables the Dialog Manager to blink the caret in editText items. In assembly
  17923. language, the code might look like this:
  17924.  
  17925.   CLR.L     -(SP)    ;event code for null event is 0
  17926.   PEA       2(SP)    ;pass null event
  17927.   CLR.L     -(SP)    ;pass NIL dialog pointer
  17928.   CLR.L     -(SP)    ;pass NIL pointer
  17929.   _DialogSelect      ;invoke DialogSelect
  17930.   ADDQ.L    #4,SP    ;pop off result and null event
  17931.  
  17932. When the accMenu message is sent to the control routine, the following information is
  17933. passed in the parameter block:  csParam contains the menu ID of the desk accessory’s
  17934. menu and csParam+2 contains the menu item number. The control routine should take the
  17935. appropriate action for when the given menu item is chosen from the menu, and then
  17936. make the Menu Manager call HiliteMenu(0) to remove the highlighting from the menu
  17937. bar.
  17938.  
  17939. Finally, the control routine should respond to one of the last five messages—accUndo
  17940. through accClear—by processing the corresponding editing command in the desk accessory
  17941. window if appropriate. SystemEdit calls the control routine with these messages. For
  17942. information on cutting and pasting between a desk accessory and the application, or
  17943. between two desk accessories, see the Scrap Manager chapter.
  17944.  
  17945. Warning:  If the accessory opens a resource file, or otherwise changes
  17946.           which file is the current resource file, it should save and
  17947.           restore the previous current resource file, using the Resource
  17948.           Manager routines CurResFile and UseResFile. Similarly, the
  17949.           accessory should save and restore the port that was the current
  17950.           grafPort, using the QuickDraw routines GetPort and SetPort.
  17951.  
  17952. _______________________________________________________________________________
  17953.  
  17954.  
  17955. æKY Summary…of…the…Desk…Manager
  17956. æC »SUMMARY OF THE DESK MANAGER                                   DeskManager
  17957. _______________________________________________________________________________
  17958.  
  17959. Routines
  17960.  
  17961. Opening and Closing Desk Accessories
  17962.  
  17963. FUNCTION OpenDeskAcc   (theAcc:  Str255) :  INTEGER;
  17964. PROCEDURE CloseDeskAcc (refNum:  INTEGER);
  17965.  
  17966. Handling Events in Desk Accessories
  17967.  
  17968. PROCEDURE SystemClick (theEvent:  EventRecord; theWindow:  WindowPtr);
  17969. FUNCTION SystemEdit   (editCmd:  INTEGER) :  BOOLEAN;
  17970.  
  17971. Performing Periodic Actions
  17972.  
  17973. PROCEDURE SystemTask;
  17974.  
  17975. Advanced Routines
  17976.  
  17977. FUNCTION SystemEvent (theEvent:  EventRecord) :  BOOLEAN;
  17978. PROCEDURE SystemMenu (menuResult:  LONGINT);
  17979.  
  17980. _______________________________________________________________________________
  17981.  
  17982. Assembly-Language Information
  17983.  
  17984. Constants
  17985.  
  17986. ; Desk accessory flag
  17987.  
  17988. dNeedTime    .EQU    5    ; set if driver needs time for performing
  17989.                           ; a periodic action
  17990.  
  17991. ; Control routine messages
  17992.  
  17993. accEvent     .EQU    64   ;handle a given event
  17994. accRun       .EQU    65   ;take the periodic action, if any,
  17995.                           ; for this desk accessory
  17996. accCursor    .EQU    66   ;change cursor shape if appropriate; generate
  17997.                           ; null event if window was created by Dialog Manager
  17998. accMenu      .EQU    67   ;handle a given menu item
  17999. accUndo      .EQU    68   ;handle the Undo command
  18000. accCut       .EQU    70   ;handle the Cut command
  18001. accCopy      .EQU    71   ;handle the Copy command
  18002. accPaste     .EQU    72   ;handle the Paste command
  18003. accClear     .EQU    73   ;handle the Clear command
  18004.  
  18005. Special Macro Names
  18006.  
  18007. Pascal name    Macro name
  18008.  
  18009. SystemEdit    _SysEdit
  18010.  
  18011. Variables
  18012.  
  18013. MBarEnable  Unique menu ID for active desk accessory, when menu bar
  18014.             belongs to the accessory (word)
  18015. SEvtEnb     0 if SystemEvent should return FALSE (byte)
  18016.  
  18017. Further Reference:
  18018. _______________________________________________________________________________
  18019. Resource Manager
  18020. QuickDraw
  18021. Toolbox Event Manager
  18022. Window Manager
  18023. Menu Manager
  18024. Device Manager
  18025. Technical Note #5, Using Modeless Dialogs from Desk Accessories
  18026. Technical Note #85, GetNextEvent; Blinking Apple Menu
  18027.  
  18028. æKY DeviceManager
  18029. æC 
  18030.  
  18031. THE DEVICE MANAGER                                                 
  18032. _______________________________________________________________________________
  18033.  
  18034. About…The…DeviceManager…Chapter
  18035. About…the…Device…Manager
  18036. Using…the…Device…Manager
  18037. Device…Manager…Routines
  18038. The…Structure…of…a…Device…Driver
  18039. Writing…Your…Own…Device…Drivers
  18040. Interrupts
  18041. The…Chooser
  18042. The…Startup…Process
  18043. Opening…Slot…Devices
  18044. Slot…Device…Interrupts
  18045. New…Routines
  18046. Summary…of…the…Device…Manager
  18047. _______________________________________________________________________________
  18048.  
  18049.  
  18050.  
  18051. æKY About…The…DeviceManager…Chapter
  18052. æC »ABOUT THIS CHAPTER                                          DeviceManager
  18053. _______________________________________________________________________________
  18054.  
  18055. This chapter describes the Device Manager, the part of the Operating System that
  18056. controls the exchange of information between a Macintosh application and devices. It
  18057. gives general information about using and writing device drivers, and also discusses
  18058. interrupts:  how the Macintosh uses them and how you can use them if you’re writing
  18059. your own device driver.
  18060.  
  18061. Note:  Specific information about the standard Macintosh drivers is
  18062.        contained in separate chapters.
  18063.  
  18064. You should already be familiar with resources, as discussed in the Resource Manager
  18065. section.
  18066.  
  18067. _______________________________________________________________________________
  18068.  
  18069.  
  18070. æKY About…the…Device…Manager
  18071. æC »ABOUT THE DEVICE MANAGER                                    DeviceManager
  18072. _______________________________________________________________________________
  18073.  
  18074. Note:  The extensions to the Device Manager described in this chapter were
  18075.        originally documented in Inside Macintosh, Volumes IV and V.  As such,
  18076.        the Volume IV information refers to the 128K ROM and System file
  18077.        version 3.2 and later, while the Volume V information refers to the
  18078.        Macintosh SE and Macintosh II ROMs and System file version 4.1 and
  18079.        later. The sections of this chapter that cover these extensions are
  18080.        so noted.
  18081.  
  18082. The Device Manager is the part of the Operating System that handles communication
  18083. between applications and devices. A device is a part of the Macintosh, or a piece of
  18084. external equipment, that can transfer information into or out of the Macintosh.
  18085. Macintosh devices include disk drives, two serial communications ports, and printers.
  18086.  
  18087. Note:  The display screen is not a device; drawing on the screen is
  18088.        handled by QuickDraw.
  18089.  
  18090. There are two kinds of devices:  character devices and block devices. A character
  18091. device reads or writes a stream of characters, or bytes, one at a time:  It can
  18092. neither skip bytes nor go back to a previous byte. A character device is used to get
  18093. information from or send information to the world outside of the Operating System and
  18094. memory:  It can be an input device, an output device, or an input/output device. The
  18095. serial ports and printers are all character devices.
  18096.  
  18097. A block device reads and writes blocks of bytes at a time; it can read or write any
  18098. accessible block on demand. Block devices are usually used to store and retrieve
  18099. information; for example, disk drives are block devices.
  18100.  
  18101. Applications communicate with devices through the Device Manager—either directly or
  18102. indirectly (through another part of the Operating System or
  18103. Toolbox). For example, an application can communicate with a disk drive directly via
  18104. the Device Manager, or indirectly via the File Manager (which calls the Device Manager).
  18105. The Device Manager doesn’t manipulate devices directly; it calls device drivers that
  18106. do (see Figure 1). Device drivers are programs that take data coming from the Device
  18107. Manager and convert them into actions of devices, or convert device actions into data
  18108. for the Device Manager to process.
  18109.  
  18110. The Operating System includes three standard device drivers in ROM:  the Disk Driver,
  18111. the Sound Driver, and the ROM Serial Driver. There are also a number of standard RAM
  18112. drivers, including the Printer Driver, the RAM Serial Driver, the AppleTalk drivers,
  18113. and desk accessories. RAM drivers are resources, and are read from the system resource
  18114. file as needed.
  18115.  
  18116. You can add other drivers independently or build on top of the existing drivers (for
  18117. example, the Printer Driver is built on top of the Serial Driver); the section “Writing
  18118. Your Own Device Drivers” describes how to do this. Desk accessories are a special
  18119. type of device driver, and are manipulated via the routines of the Desk Manager.
  18120.  
  18121. •••Refer to Figure 1.•••
  18122.  
  18123. Figure 1–Communication with Devices
  18124.  
  18125. Warning:  Information about desk accessories covered in the Desk Manager
  18126.           chapter is not repeated here. Some information in this chapter
  18127.           may not apply to desk accessories.
  18128.  
  18129. A device driver can be either open or closed. The Sound Driver and Disk Driver are
  18130. opened when the system starts up; the rest of the drivers are opened at the specific
  18131. request of an application. After a driver has been opened, an application can read
  18132. data from and write data to it. You can close device drivers that are no longer in
  18133. use, and recover the memory used by them. Up to 32 device drivers may be open at any
  18134. one time.
  18135.  
  18136. Before it’s opened, you identify a device driver by its driver name; after it’s
  18137. opened, you identify it by its reference number. A driver name consists of a period
  18138. (.) followed by any sequence of 1 to 254 printing characters. A RAM driver’s name is
  18139. the same as its resource name. You can use uppercase and lowercase letters when
  18140. naming drivers, but the Device Manager ignores case when comparing names (it doesn’t
  18141. ignore diacritical marks).
  18142.  
  18143. Note:  Although device driver names can be quite long, there’s little
  18144.        reason for them to be more than a few characters in length.
  18145.  
  18146. The Device Manager assigns each open device driver a driver reference number, from –1
  18147. to –32, that’s used instead of its driver name to refer to it.
  18148.  
  18149. Most communication between an application and an open device driver occurs by reading
  18150. and writing data. Data read from a driver is placed in the
  18151. application’s data buffer, and data written to a driver is taken from the application’s
  18152. data buffer. A data buffer is memory allocated by the application for communication
  18153. with drivers.
  18154.  
  18155. In addition to data that’s read from or written to device drivers, drivers may require
  18156. or provide other information. Information transmitted to a driver by an application
  18157. is called control information; information provided by a driver is called status
  18158. information. Control information may select modes of operation, start or stop processes,
  18159. enable buffers, choose protocols, and so on. Status information may indicate the
  18160. current mode of operation, the readiness of the device, the occurrence of errors, and
  18161. so on. Each device driver may respond to a number of different types of control
  18162. information and may provide a number of different types of status information.
  18163.  
  18164. Each of the standard Macintosh drivers includes predefined calls for transmitting
  18165. control information and receiving status information. Explanations of these calls can
  18166. be found in the chapters describing the drivers.
  18167.  
  18168. Note:  The extensions to the Device Manager described in the following
  18169.        paragraphs were originally documented in Inside Macintosh, Volume IV.
  18170.        As such, this information refers to the 128K ROMs and System file
  18171.        version 3.2 and later.
  18172.  
  18173. While no new routines have been added to the Device Manager with the Macintosh Plus,
  18174. the handling of the existing routines has been significantly improved.
  18175.  
  18176. When an Open call is made, installed drivers are searched first (before resources) to
  18177. avoid replacing a current driver; this search is done by name so be sure that your
  18178. driver’s name is in the driver header. All drivers, exclusive of desk accessories,
  18179. must have a name that begins with a period; otherwise, the Open call is passed on to
  18180. the File Manager.
  18181.  
  18182. If a driver is already open, Open calls will not be sent to the driver’s open routine,
  18183. preserving its device control entry. A desk accessory will, however, receive another
  18184. call (certain desk accessories count on this).
  18185.  
  18186. If a driver fails to open because of a resource load problem, the Open call terminates
  18187. with the appropriate error code instead of being passed on to the File Manager (which
  18188. would usually return the result code fnfErr). If a driver returns a negative result
  18189. code in register D0 from an Open call, the result code is passed back and the driver
  18190. is not opened. If a driver returns the result code closeErr in register D0 from a
  18191. Close call, this result code is passed back and the driver is not closed.
  18192.  
  18193. Open, Close, Read, Write, Control, and Status return all results in the ioResult
  18194. field as well as in register D0. A KillIO call is passed to the driver only if it’s
  18195. open and enabled for Control calls.
  18196.  
  18197. The number of device control entries in the 128K ROM has been increased from 32 to
  18198. 48. The unit table is now a 192-byte nonrelocatable block containing 48
  18199. four-byte entries; the standard unit table assignments are as follows:
  18200.  
  18201. Unit Number  Device
  18202.  
  18203.       0      Reserved
  18204.       1      Hard disk driver: Macintosh XL internal or Hard Disk 20 external
  18205.       2      .Print driver
  18206.       3      .Sound driver
  18207.       4      .Sony driver
  18208.       5      Modem port asynchronous driver input (.AIn)
  18209.       6      Modem port asynchronous driver output (.AOut)
  18210.       7      Printer port asynchronous driver input (.BIn)
  18211.       8      Printer port asynchronous driver output (.BOut)
  18212.       9      AppleTalk .MPP driver
  18213.       10     AppleTalk .ATP driver
  18214.       11     Reserved
  18215.       12–26  Desk accessories in System file
  18216.       27–31  Desk accessories in application files
  18217.       32–39  SCSI drivers 0–7
  18218.       40–47  Reserved
  18219.  
  18220. Note:  The extensions to the Device Manager described in the following
  18221.        paragraphs were originally documented in Inside Macintosh, Volume V.
  18222.        As such, this information refers to the Macintosh SE and Macintosh II
  18223.        ROMs and System file version 4.1 and later.
  18224.  
  18225. New modifications have been made to the Device Manager to support slot devices.
  18226.  
  18227. Reader’s guide:  You need the information in the slot-related sections of
  18228.                  this chapter only if your application uses a specific card
  18229.                  (other than a standard video card) that plugs into a NuBus™
  18230.                  slot on the Macintosh II.
  18231.  
  18232. These slot-related sections cover the following subjects:
  18233.  
  18234.   •  the parts of the system startup procedure that affect slot devices
  18235.   •  how the Open call now handles slot devices
  18236.   •  how interrupts originating in slot devices are processed
  18237.   •  how the new Chooser works with slot devices
  18238.  
  18239. You’ll also need to be familiar with
  18240.  
  18241.   •   the Start Manager
  18242.   •   the Slot Manager
  18243.   •   the parts of the book “Designing Cards and Drivers for Macintosh
  18244.       II and Macintosh SE” that pertain to the device your application uses.
  18245.  
  18246. _______________________________________________________________________________
  18247.  
  18248.  
  18249. æKY Using…the…Device…Manager
  18250. æC »USING THE DEVICE MANAGER                                    DeviceManager
  18251. _______________________________________________________________________________
  18252.  
  18253. You can call Device Manager routines via three different methods:  high-level Pascal
  18254. calls, low-level Pascal calls, and assembly language. The high-level Pascal calls are
  18255. designed for Pascal programmers interested in using the Device Manager in a simple
  18256. manner; they provide adequate device I/O and don’t require much special knowledge to
  18257. use. The low-level Pascal and assembly-language calls are designed for advanced
  18258. Pascal programmers and assembly-language programmers interested in using the Device
  18259. Manager to its fullest capacity; they require some special knowledge to be used most
  18260. effectively.
  18261.  
  18262. Note:  The names used to refer to routines here are actually
  18263.        assembly-language macro names for the low-level routines,
  18264.        but the Pascal routine names are very similar.
  18265.  
  18266. The Device Manager is automatically initialized each time the system starts up.
  18267.  
  18268. Before an application can exchange information with a device driver, the driver must
  18269. be opened. The Sound Driver and Disk Driver are opened when the system starts up; for
  18270. other drivers, the application must call Open. The Open routine will return the
  18271. driver reference number that you’ll use every time you want to refer to that device
  18272. driver.
  18273.  
  18274. An application can send data from its data buffer to an open driver with a Write
  18275. call, and transfer data from an open driver to its data buffer with Read. An application
  18276. passes control information to a device driver by calling Control, and receives status
  18277. information from a driver by calling Status.
  18278.  
  18279. Whenever you want to stop a device driver from completing I/O initiated by a Read,
  18280. Write, Control, or Status call, call KillIO. KillIO halts any current I/O and deletes
  18281. any pending I/O.
  18282.  
  18283. When you’re through using a driver, call Close. Close forces the device driver to
  18284. complete any pending I/O, and then releases all the memory used by the driver.
  18285.  
  18286. _______________________________________________________________________________
  18287.  
  18288.  
  18289. æKY Device…Manager…Routines
  18290. æC »DEVICE MANAGER ROUTINES                                     DeviceManager
  18291. _______________________________________________________________________________
  18292.  
  18293. This section describes the Device Manager routines used to call drivers. It’s divided
  18294. into two parts:  The first describes all the high-level Pascal routines of the Device
  18295. Manager, and the second presents information about calling the low-level Pascal and
  18296. assembly-language routines.
  18297.  
  18298. All the Device Manager routines in this section return an integer result code of type
  18299. OSErr. Each routine description lists all of the applicable result codes, along with
  18300. a short description of what the result code means. Lengthier explanations of all the
  18301. result codes can be found in the summary at the end of this chapter.
  18302.  
  18303. _______________________________________________________________________________
  18304.  
  18305. »High-Level Device Manager Routines
  18306.  
  18307. Note:  As described in the File Manager chapter, the FSRead and FSWrite
  18308.        routines are also used to read from and write to files.
  18309.  
  18310. FUNCTION OpenDriver (name:  Str255; VAR refNum:  INTEGER) :  OSErr; [Not in ROM]
  18311.  
  18312. OpenDriver opens the device driver specified by name and returns its reference number
  18313. in refNum.
  18314.  
  18315. Result codes    noErr           No error
  18316.                 badUnitErr      Bad reference number
  18317.                 dInstErr        Couldn’t find driver in resource file
  18318.                 openErr         Driver can’t perform the requested
  18319.                                 reading or writing
  18320.                 unitEmptyErr    Bad reference number
  18321.  
  18322. FUNCTION CloseDriver (refNum:  INTEGER) :  OSErr; [Not in ROM]
  18323.  
  18324. CloseDriver closes the device driver having the reference number refNum. Any pending
  18325. I/O is completed, and the memory used by the driver is released.
  18326.  
  18327. Warning:  Before using this command to close a particular driver, refer
  18328.           to the chapter describing the driver for the consequences of
  18329.           closing it.
  18330.  
  18331. Result codes    noErr           No error
  18332.                 badUnitErr      Bad reference number
  18333.                 dRemoveErr      Attempt to remove an open driver
  18334.                 unitEmptyErr    Bad reference number
  18335.  
  18336. FUNCTION FSRead (refNum:  INTEGER; VAR count:  LONGINT;
  18337.                  buffPtr:  Ptr) :  OSErr; [Not in ROM]
  18338.  
  18339. FSRead attempts to read the number of bytes specified by the count parameter from the
  18340. open device driver having the reference number refNum, and transfer them to the data
  18341. buffer pointed to by buffPtr. After the read operation is completed, the number of
  18342. bytes actually read is returned in the count parameter.
  18343.  
  18344. Result codes    noErr           No error
  18345.                 badUnitErr      Bad reference number
  18346.                 notOpenErr      Driver isn’t open
  18347.                 unitEmptyErr    Bad reference number
  18348.                 readErr         Driver can’t respond to Read calls
  18349.  
  18350. FUNCTION FSWrite (refNum:  INTEGER; VAR count:  LONGINT;
  18351.                   buffPtr:  Ptr) :  OSErr; [Not in ROM]
  18352.  
  18353. FSWrite takes the number of bytes specified by the count parameter from the buffer
  18354. pointed to by buffPtr and attempts to write them to the open device driver having the
  18355. reference number refNum. After the write operation is completed, the number of bytes
  18356. actually written is returned in the count parameter.
  18357.  
  18358. Result codes    noErr           No error
  18359.                 badUnitErr      Bad reference number
  18360.                 notOpenErr      Driver isn’t open
  18361.                 unitEmptyErr    Bad reference number
  18362.                 writErr         Driver can’t respond to Write calls
  18363.  
  18364. FUNCTION Control (refNum:  INTEGER; csCode:  INTEGER;
  18365.                   csParamPtr:  Ptr) :  OSErr; [Not in ROM]
  18366.  
  18367. Control sends control information to the device driver having the reference number
  18368. refNum. The type of information sent is specified by csCode, and the information
  18369. itself is pointed to by csParamPtr. The values passed in csCode and pointed to by
  18370. csParamPtr depend on the driver being called.
  18371.  
  18372. Result codes    noErr           No error
  18373.                 badUnitErr      Bad reference number
  18374.                 notOpenErr      Driver isn’t open
  18375.                 unitEmptyErr    Bad reference number
  18376.                 controlErr      Driver can’t respond to this Control call
  18377.  
  18378. FUNCTION Status (refNum:  INTEGER; csCode:  INTEGER;
  18379.                  csParamPtr:  Ptr) :  OSErr; [Not in ROM]
  18380.  
  18381. Status returns status information about the device driver having the reference number
  18382. refNum. The type of information returned is specified by csCode, and the information
  18383. itself is pointed to by csParamPtr. The values passed in csCode and pointed to by
  18384. csParamPtr depend on the driver being called.
  18385.  
  18386. Result codes    noErr           No error
  18387.                 badUnitErr      Bad reference number
  18388.                 notOpenErr      Driver isn’t open
  18389.                 unitEmptyErr    Bad reference number
  18390.                 statusErr       Driver can’t respond to this Status call
  18391.  
  18392. FUNCTION KillIO (refNum:  INTEGER) :  OSErr; [Not in ROM]
  18393.  
  18394. KillIO terminates all current and pending I/O with the device driver having the
  18395. reference number refNum.
  18396.  
  18397. Result codes    noErr           No error
  18398.                 badUnitErr      Bad reference number
  18399.                 unitEmptyErr    Bad reference number
  18400.  
  18401. _______________________________________________________________________________
  18402.  
  18403. »Low-Level Device Manager Routines
  18404.  
  18405. This section contains special information for programmers using the low-level Pascal
  18406. or assembly-language routines of the Device Manager, and describes them in detail.
  18407.  
  18408. Note:  The Device Manager routines for writing device drivers are
  18409.        described in the section “Writing Your Own Device Drivers”.
  18410.  
  18411. All low-level Device Manager routines can be executed either synchronously
  18412. (meaning that the application can’t continue until the routine is completed) or
  18413. asynchronously (meaning that the application is free to perform other tasks while the
  18414. routine is executing). Some cannot be executed asynchronously, because they use the
  18415. Memory Manager to allocate and release memory.
  18416.  
  18417. When an application calls a Device Manager routine asynchronously, an I/O request is
  18418. placed in the driver I/O queue, and control returns to the calling program—possibly
  18419. even before the actual I/O is completed. Requests are taken from the queue one at a
  18420. time, and processed; meanwhile, the calling program is free to work on other things.
  18421.  
  18422. The calling program may specify a completion routine to be executed at the end of an
  18423. asynchronous operation.
  18424.  
  18425. Routine parameters passed by an application to the Device Manager and returned by the
  18426. Device Manager to an application are contained in a parameter block, which is a data
  18427. structure in the heap or stack. All low-level Pascal calls to the Device Manager are
  18428. of the form
  18429.  
  18430. FUNCTION PBCallName (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18431.  
  18432. PBCallName is the name of the routine. ParamBlock points to the parameter block
  18433. containing the parameters for the routine. If async is TRUE, the call is executed
  18434. asynchronously; otherwise the call is executed synchronously. Each call returns an
  18435. integer result code of type OSErr.
  18436.  
  18437. Assembly-language note:  When you call a Device Manager routine, A0 must
  18438.                          point to a parameter block containing the
  18439.                          parameters for the routine. If you want the
  18440.                          routine to be executed asynchronously, set bit 10
  18441.                          of the routine trap word. You can do this by
  18442.                          supplying the word ASYNC as the second argument
  18443.                          to the routine macro. For example:
  18444.  
  18445.                            _Read ,ASYNC
  18446.  
  18447.                          You can set or test bit 10 of a trap word by using
  18448.                          the global constant asyncTrpBit.
  18449.  
  18450.                          If you want a routine to be executed immediately
  18451.                          (bypassing the driver I/O queue), set bit 9 of the
  18452.                          routine trap word. This can be accomplished by
  18453.                          supplying the word IMMED as the second argument
  18454.                          to the routine macro. (The driver must be able to
  18455.                          handle immediate calls for this to work.) For example:
  18456.  
  18457.                            _Write ,IMMED
  18458.  
  18459.                          You can set or test bit 9 of a trap word by using
  18460.                          the global constant noQueueBit. You can specify
  18461.                          either ASYNC or IMMED, but not both. (The syntax
  18462.                          shown above applies to the Macintosh Programmers
  18463.                          Workshop Assembler; programmers using another
  18464.                          development system should consult its documentation
  18465.                          for the proper syntax.)
  18466.  
  18467.                          All routines return a result code in D0.
  18468.  
  18469. »Routine Parameters
  18470.  
  18471. There are two different kinds of parameter blocks you’ll pass to Device Manager
  18472. routines:  one for I/O routines and another for Control and Status calls.
  18473.  
  18474. The lengthy, variable-length data structure of a parameter block is given below. The
  18475. Device Manager and File Manager use this same data structure, but only the parts
  18476. relevant to the Device Manager are discussed here. Each kind of parameter block
  18477. contains eight fields of standard information and three to nine fields of additional
  18478. information:
  18479.  
  18480. TYPE  ParamBlkType  = (ioParam,fileParam,volumeParam,cntrlParam);
  18481.  
  18482.       ParamBlockRec = RECORD
  18483.                         qLink:         QElemPtr;  {next queue entry}
  18484.                         qType:         INTEGER;   {queue type}
  18485.                         ioTrap:        INTEGER;   {routine trap}
  18486.                         ioCmdAddr:     Ptr;       {routine address}
  18487.                         ioCompletion:  ProcPtr;   {completion routine}
  18488.                         ioResult:      OSErr;     {result code}
  18489.                         ioNamePtr:     StringPtr; {driver name}
  18490.                         ioVRefNum:     INTEGER;   {volume reference or }
  18491.                                                   { drive number}
  18492.                         CASE ParamBlkType OF
  18493.                            ioParam:
  18494.                             . . . {I/O routine parameters}
  18495.                            fileParam:
  18496.                             . . . {used by the File Manager}
  18497.                            volumeParam:
  18498.                             . . . {used by the File Manager}
  18499.                            cntrlParam:
  18500.                             . . . {Control and Status call parameters}
  18501.                       END;
  18502.  
  18503.       ParmBlkPtr = ^ParamBlockRec;
  18504.  
  18505. The first four fields in each parameter block are handled entirely by the Device
  18506. Manager, and most programmers needn’t be concerned with them; programmers who are
  18507. interested in them should see the section “The Structure of a Device Driver”.
  18508.  
  18509. IOCompletion contains a pointer to a completion routine to be executed at the end of
  18510. an asynchronous call; it should be NIL for asynchronous calls with no completion
  18511. routine, and is automatically set to NIL for all synchronous calls.
  18512.  
  18513. Warning:  Completion routines are executed at the interrupt level and must
  18514.           preserve all registers other than A0, A1, and D0-D2. Your completion
  18515.           routine must not make any calls to the Memory Manager, directly or
  18516.           indirectly, and can’t depend on handles to unlocked blocks being
  18517.           valid. If it uses application globals, it must also ensure that
  18518.           register A5 contains the address of the boundary between the
  18519.           application globals and the application parameters; for details,
  18520.           see SetCurrentA5 and SetA5 in Macintosh Technical Note #208.
  18521.  
  18522. •••Refer to Technical Note #208:•••
  18523.  
  18524. Assembly-language note:  When your completion routine is called, register A0
  18525.                          points to the parameter block of the asynchronous
  18526.                          call and register D0 contains the result code.
  18527.  
  18528. Routines that are executed asynchronously return control to the calling program with
  18529. the result code noErr as soon as the call is placed in the driver I/O queue. This
  18530. isn’t an indication of successful call completion, but simply indicates that the call
  18531. was successfully queued. To determine when the call is actually completed, you can
  18532. poll the ioResult field; this field is set to 1 when the call is made, and receives
  18533. the actual result code upon completion of the call. Completion routines are executed
  18534. after the result code is placed in ioResult.
  18535.  
  18536. IONamePtr is a pointer to the name of a driver and is used only for calls to the Open
  18537. function. IOVRefNum is used by the Disk Driver to identify drives.
  18538.  
  18539. I/O routines use the following additional fields:
  18540.  
  18541. ioParam:
  18542.     (ioRefNum:     INTEGER;     {driver reference number}
  18543.      ioVersNum:    SignedByte;  {not used}
  18544.      ioPermssn:    SignedByte;  {read/write permission}
  18545.      ioMisc:       Ptr;         {not used}
  18546.      ioBuffer:     Ptr;         {pointer to data buffer}
  18547.      ioReqCount:   LONGINT;     {requested number of bytes}
  18548.      ioActCount:   LONGINT;     {actual number of bytes}
  18549.      ioPosMode:    INTEGER;     {positioning mode}
  18550.      ioPosOffset:  LONGINT);    {positioning offset}
  18551.  
  18552. IOPermssn requests permission to read from or write to a driver when the driver is
  18553. opened, and must contain one of the following values:
  18554.  
  18555. CONST  fsCurPerm   = 0;    {whatever is currently allowed}
  18556.        fsRdPerm    = 1;    {request to read only}
  18557.        fsWrPerm    = 2;    {request to write only}
  18558.        fsRdWrPerm  = 3;    {request to read and write}
  18559.  
  18560. This request is compared with the capabilities of the driver (some drivers are read-only,
  18561. some are write-only). If the driver is incapable of performing as requested, a result
  18562. code indicating the error is returned.
  18563.  
  18564. IOBuffer points to a data buffer into which data is written by Read calls and from
  18565. which data is read by Write calls. IOReqCount specifies the requested number of bytes
  18566. to be read or written. IOActCount contains the number of bytes actually read or
  18567. written.
  18568.  
  18569. IOPosMode and ioPosOffset contain positioning information used for Read and Write
  18570. calls by drivers of block devices. IOPosMode contains the positioning mode; bits 0
  18571. and 1 indicate where an operation should begin relative to the physical beginning of
  18572. the block-formatted medium (such as a disk). You can use the following predefined
  18573. constants to test or set the value of these bits:
  18574.  
  18575. CONST  fsAtMark    = 0;    {at current position}
  18576.        fsFromStar  = 1;    {offset relative to beginning of medium}
  18577.        fsFromMark  = 3;    {offset relative to current position}
  18578.  
  18579. IOPosOffset specifies the byte offset (either positive or negative), relative to the
  18580. position specified by the positioning mode, where the operation will be performed
  18581. (except when the positioning mode is fsAtMark, in which case ioPosOffset is ignored).
  18582. IOPosOffset must be a 512-byte multiple.
  18583.  
  18584. To verify that data written to a block device matches the data in memory, make a Read
  18585. call right after the Write call. The parameters for a read-verify operation are the
  18586. same as for a standard Read call, except that the following constant must be added to
  18587. the positioning mode:
  18588.  
  18589.   CONST rdVerify = 64; {read-verify mode}
  18590.  
  18591. The result code ioErr is returned if any of the data doesn’t match.
  18592.  
  18593. Control and Status calls use three additional fields:
  18594.  
  18595. cntrlParam:
  18596.     (ioCRefNum:  INTEGER;                  {driver reference number}
  18597.      csCode:     INTEGER;                  {type of Control or Status call}
  18598.      csParam:    ARRAY[0..10] OF INTEGER); {control or status information}
  18599.  
  18600. IOCRefNum contains the reference number of the device driver. The csCode field contains
  18601. a number identifying the type of call; this number may be interpreted differently by
  18602. each driver. The csParam field contains the control or status information for the
  18603. call; it’s declared as up to 22 bytes of information because its exact contents will
  18604. vary from one Control or Status call to the next. To store information in this field,
  18605. you must perform the proper type coercion.
  18606. _______________________________________________________________________________
  18607.  
  18608. »Routine Descriptions
  18609.  
  18610. This section describes the procedures and functions. Each routine description includes
  18611. the low-level Pascal form of the call and the routine’s assembly-language macro. A
  18612. list of the fields in the parameter block affected by the call is also given.
  18613.  
  18614. Assembly-language note:  The field names given in these descriptions are
  18615.                          those of the ParamBlockRec data type; see the
  18616.                          summary at the end of this chapter for the names
  18617.                          of the corresponding assembly-language offsets.
  18618.                          (The names for some offsets differ from their
  18619.                          Pascal equivalents, and in certain cases more than
  18620.                          one name for the same offset is provided.)
  18621.  
  18622. The number next to each parameter name indicates the byte offset of the parameter
  18623. from the start of the parameter block pointed to by register A0; only assembly-language
  18624. programmers need be concerned with it. An arrow next to each parameter name indicates
  18625. whether it’s an input, output, or input/output parameter:
  18626.  
  18627. Arrow    Meaning
  18628.  
  18629.   -->    Parameter is passed to the routine
  18630.   <--    Parameter is returned by the routine
  18631.   <->    Parameter is passed to and returned by the routine
  18632.  
  18633. Note:  As described in the File Manager chapter, the Open and Close
  18634.        functions are also used to open and close files.
  18635.  
  18636. FUNCTION PBOpen (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18637.  
  18638. Parameter block
  18639.   -->    12    ioCompletion  pointer
  18640.   <--    16    ioResult      word
  18641.   -->    18    ioNamePtr     pointer
  18642.   <--    24    ioRefNum      word
  18643.   -->    27    ioPermssn     byte
  18644.  
  18645. PBOpen opens the device driver specified by ioNamePtr, reading it into memory if
  18646. necessary, and returns its reference number in ioRefNum. IOPermssn specifies the
  18647. requested read/write permission.
  18648.  
  18649. Result codes    noErr           No error
  18650.                 badUnitErr      Bad reference number
  18651.                 dInstErr        Couldn’t find driver in resource file
  18652.                 openErr         Driver can’t perform the requested
  18653.                                 reading or writing
  18654.                 unitEmptyErr    Bad reference number
  18655.  
  18656. FUNCTION PBClose (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18657.  
  18658. Trap macro    _Close
  18659.  
  18660. Parameter block
  18661.   -->    12    ioCompletion  pointer
  18662.   <--    16    ioResult      word
  18663.   -->    24    ioRefNum      word
  18664.  
  18665. PBClose closes the device driver having the reference number ioRefNum. Any pending
  18666. I/O is completed, and the memory used by the driver is released.
  18667.  
  18668. Result codes    noErr           No error
  18669.                 badUnitErr      Bad reference number
  18670.                 dRemovErr       Attempt to remove an open driver
  18671.                 unitEmptyErr    Bad reference number
  18672.  
  18673. FUNCTION PBRead (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18674.  
  18675. Trap macro    _Read
  18676.  
  18677. •••Refer to Technical Note #187:•••
  18678.  
  18679. Parameter block
  18680.   -->    12    ioCompletion  pointer
  18681.   <--    16    ioResult      word
  18682.   -->    22    ioVRefNum     word
  18683.   -->    24    ioRefNum      word
  18684.   -->    32    ioBuffer      pointer
  18685.   -->    36    ioReqCount    long word
  18686.   <--    40    ioActCount    long word
  18687.   -->    44    ioPosMode     word
  18688.   <->    46    ioPosOffset   long word
  18689.  
  18690. PBRead attempts to read ioReqCount bytes from the device driver having the reference
  18691. number ioRefNum, and transfer them to the data buffer pointed to by ioBuffer. The
  18692. drive number, if any, of the device to be read from is specified by ioVRefNum. After
  18693. the read is completed, the position is returned in ioPosOffset and the number of
  18694. bytes actually read is returned in ioActCount.
  18695.  
  18696. Result codes    noErr           No error
  18697.                 badUnitErr      Bad reference number
  18698.                 notOpenErr      Driver isn’t open
  18699.                 unitEmptyErr    Bad reference number
  18700.                 readErr         Driver can’t respond to Read calls
  18701.  
  18702. FUNCTION PBWrite (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18703.  
  18704. Trap macro    _Write
  18705.  
  18706. •••Refer to Technical Note #187:•••
  18707.  
  18708. Parameter block
  18709.   -->    12    ioCompletion  pointer
  18710.   <--    16    ioResult      word
  18711.   -->    22    ioVRefNum     word
  18712.   -->    24    ioRefNum      word
  18713.   -->    32    ioBuffer      pointer
  18714.   -->    36    ioReqCount    long word
  18715.   <--    40    ioActCount    long word
  18716.   -->    44    ioPosMode     word
  18717.   <->    46    ioPosOffset   long word
  18718.  
  18719. PBWrite takes ioReqCount bytes from the buffer pointed to by ioBuffer and attempts to
  18720. write them to the device driver having the reference number ioRefNum. The drive
  18721. number, if any, of the device to be written to is specified by ioVRefNum. After the
  18722. write is completed, the position is returned in ioPosOffset and the number of bytes
  18723. actually written is returned in ioActCount.
  18724.  
  18725. Result codes    noErr           No error
  18726.                 badUnitErr      Bad reference number
  18727.                 notOpenErr      Driver isn’t open
  18728.                 unitEmptyErr    Bad reference number
  18729.                 writErr         Driver can’t respond to Write calls
  18730.  
  18731. FUNCTION PBControl (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18732.  
  18733. Trap macro    _Control
  18734.  
  18735. Parameter block
  18736.   -->    12    ioCompletion  pointer
  18737.   <--    16    ioResult      word
  18738.   -->    22    ioVRefNum     word
  18739.   -->    24    ioRefNum      word
  18740.   -->    26    csCode        word
  18741.   -->    28    csParam       record
  18742.  
  18743. PBControl sends control information to the device driver having the reference number
  18744. ioRefNum; the drive number, if any, is specified by ioVRefNum. The type of information
  18745. sent is specified by csCode, and the information itself begins at csParam. The values
  18746. passed in csCode and csParam depend on the driver being called.
  18747.  
  18748. Result codes    noErr           No error
  18749.                 badUnitErr      Bad reference number
  18750.                 notOpenErr      Driver isn’t open
  18751.                 unitEmptyErr    Bad reference number
  18752.                 controlErr      Driver can’t respond to this Control call
  18753.  
  18754. FUNCTION PBStatus (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18755.  
  18756. Trap macro    _Status
  18757.  
  18758. Parameter block
  18759.   -->    12    ioCompletion  pointer
  18760.   <--    16    ioResult      word
  18761.   -->    22    ioVRefNum     word
  18762.   -->    24    ioRefNum      word
  18763.   -->    26    csCode        word
  18764.   <--    28    csParam       record
  18765.  
  18766. PBStatus returns status information about the device driver having the reference
  18767. number ioRefNum; the drive number, if any, is specified by ioVRefNum. The type of
  18768. information returned is specified by csCode, and the information itself begins at
  18769. csParam. The values passed in csCode and csParam depend on the driver being called.
  18770.  
  18771. Result codes    noErr           No error
  18772.                 badUnitErr      Bad reference number
  18773.                 notOpenErr      Driver isn’t open
  18774.                 unitEmptyErr    Bad reference number
  18775.                 statusErr       Driver can’t respond to this Status call
  18776.  
  18777. FUNCTION PBKillIO (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  18778.  
  18779. Trap macro    _KillIO
  18780.  
  18781. Parameter block
  18782.   -->    12    ioCompletion  pointer
  18783.   <--    16    ioResult      word
  18784.   -->    24    ioRefNum      word
  18785.  
  18786. PBKillIO stops any current I/O request being processed, and removes all pending I/O
  18787. requests from the I/O queue of the device driver having the reference number ioRefNum.
  18788. The completion routine of each pending I/O request is called, with the ioResult field
  18789. of each request equal to the result code abortErr.
  18790.  
  18791. Result codes    noErr           No error
  18792.                 badUnitErr      Bad reference number
  18793.                 unitEmptyErr    Bad reference number
  18794.  
  18795. _______________________________________________________________________________
  18796.  
  18797.  
  18798. æKY The…Structure…of…a…Device…Driver
  18799. æC »THE STRUCTURE OF A DEVICE DRIVER                            DeviceManager
  18800. _______________________________________________________________________________
  18801.  
  18802. This section describes the structure of device drivers for programmers interested in
  18803. writing their own driver or manipulating existing drivers. Some of the information
  18804. presented here is accessible only through assembly language.
  18805.  
  18806. RAM drivers are stored in resource files. The resource type for drivers is
  18807. 'DRVR'. The resource name is the driver name. The resource ID for a driver is its
  18808. unit number (explained below) and must be between 0 and 31 inclusive.
  18809.  
  18810. Warning:  Don’t use the unit number of an existing driver unless you
  18811.           want the existing driver to be replaced.
  18812.  
  18813. As shown in Figure 2, a driver begins with a few words of flags and other data,
  18814. followed by offsets to the routines that do the work of the driver, an optional
  18815. title, and finally the routines themselves.
  18816.  
  18817. Every driver contains a routine to handle Open and Close calls, and may contain
  18818. routines to handle Read, Write, Control, Status, and KillIO calls. The driver routines
  18819. that handle Device Manager calls are as follows:
  18820.  
  18821.   Device Manager call    Driver routine
  18822.  
  18823.       Open                   Open
  18824.       Read                   Prime
  18825.       Write                  Prime
  18826.       Control                Control
  18827.       KillIO                 Control
  18828.       Status                 Status
  18829.       Close                  Close
  18830.  
  18831. •••Refer to Figure 2.•••
  18832.  
  18833. Figure 2–Driver Structure
  18834.  
  18835. For example, when a KillIO call is made to a driver, the driver’s control routine
  18836. must implement the call.
  18837.  
  18838. Each bit of the high-order byte of the drvrFlags word contains a flag:
  18839.  
  18840.   dReadEnable   .EQU    0  ;set if driver can respond to Read calls
  18841.   dWritEnable   .EQU    1  ;set if driver can respond to Write calls
  18842.   dCtlEnable    .EQU    2  ;set if driver can respond to Control calls
  18843.   dStatEnable   .EQU    3  ;set if driver can respond to Status calls
  18844.   dNeedGoodBye  .EQU    4  ;set if driver needs to be called before
  18845.                            ; the application heap is reinitialized
  18846.   dNeedTime     .EQU    5  ;set if driver needs time for performing
  18847.                            ; a periodic action
  18848.   dNeedLock     .EQU    6  ;set if driver will be locked in memory as
  18849.                            ; soon as it's opened (always set for ROM drivers)
  18850.  
  18851. Bits 8-11 (bits 0-3 of the high-order byte) indicate which Device Manager calls the
  18852. driver’s routines can respond to.
  18853.  
  18854. Unlocked RAM drivers in the application heap will be lost every time the heap is
  18855. reinitialized (when an application starts up, for example). If dNeedGoodBye is set,
  18856. the control routine of the device driver will be called before the heap is reinitialized,
  18857. and the driver can perform any “clean-up” actions it needs to. The driver’s control
  18858. routine identifies this “good-bye” call by checking the csCode parameter—it will be
  18859. the global constant
  18860.  
  18861.   goodBye    .EQU    -1  ;heap will be reinitialized, clean up if necessary
  18862.  
  18863. Device drivers may need to perform predefined actions periodically. For example, a
  18864. network driver may want to poll its input buffer every ten seconds to see if it has
  18865. received any messages. If the dNeedTime flag is set, the driver does need to perform
  18866. a periodic action, and the drvrDelay word contains a tick count indicating how often
  18867. the periodic action should occur. A tick count of 0 means it should happen as often
  18868. as possible, 1 means it should happen at most every sixtieth of a second, 2 means at
  18869. most every thirtieth of a second, and so on. Whether the action actually occurs this
  18870. frequently depends on how often the application calls the Desk Manager procedure
  18871. SystemTask. SystemTask calls the driver’s control routine (if the time indicated by
  18872. drvrDelay has elapsed), and the control routine must perform whatever predefined
  18873. action is desired. The driver’s control routine identifies the SystemTask call by
  18874. checking the csCode parameter—it will be the global constant
  18875.  
  18876.   accRun    .EQU    65  ;take the periodic action, if any, for this driver
  18877.  
  18878. Note:  Some drivers may not want to rely on the application to call
  18879.        SystemTask. The Vertical Retrace Manager and Time Manager both offer
  18880.        the ability to perform tasks periodically. Both of these alternatives,
  18881.        however, perform these tasks at interrupt time, and there are certain
  18882.        restrictions on tasks performed during interrupts, such as not
  18883.        being able to make calls to the Memory Manager. For more information
  18884.        on these restrictions, see the Vertical Retrace Manager, and Time
  18885.        Manager chapters. Tasks that are time consuming may be able to take
  18886.        advantage of the Deferred Task Manager, which will allow other
  18887.        interrupts to be processed. Periodic actions performed in response to
  18888.        SystemTask calls are not performed via an interrupt and so don’t have
  18889.        these restrictions.
  18890.  
  18891. DrvrEMask and drvrMenu are used only for desk accessories and are discussed in the
  18892. Desk Manager chapter.
  18893.  
  18894. Following drvrMenu are the offsets to the driver routines, a title for the driver
  18895. (preceded by its length in bytes), and the routines that do the work of the driver.
  18896.  
  18897. Note:  Each of the driver routines must be aligned on a word boundary.
  18898.  
  18899. _______________________________________________________________________________
  18900.  
  18901. »Device Control Entry
  18902.  
  18903. The first time a driver is opened, information about it is read into a structure in
  18904. memory called a device control entry. A device control entry contains the header of
  18905. the driver’s I/O queue, the location of the driver’s routines, and other information.
  18906. A device control entry is a 40-byte relocatable block located in the system heap.
  18907. It’s locked while the driver is open, and unlocked while the driver is closed.
  18908.  
  18909. Most of the data in the device control entry is stored and accessed only by the
  18910. Device Manager, but in some cases the driver itself must store into it. The structure
  18911. of a device control entry is shown below; note that the first four words of the
  18912. driver are copied into the dCtlFlags, dCtlDelay, dCtlEMask, and dCtlMenu fields.
  18913.  
  18914. TYPE  DCtlEntry = RECORD
  18915.                     dCtlDriver:    Ptr;        {pointer to ROM driver or }
  18916.                                                { handle to RAM driver}
  18917.                     dCtlFlags:     INTEGER;    {flags}
  18918.                     dCtlQHdr:      QHdr;       {driver I/O queue header}
  18919.                     dCtlPosition:  LONGINT;    {byte position used by Read }
  18920.                                                { and Write calls}
  18921.                     dCtlStorage:   Handle;     {handle to RAM driver's }
  18922.                                                { private storage}
  18923.                     dCtlRefNum:    INTEGER;    {driver reference number}
  18924.                     dCtlCurTicks:  LONGINT;    {used internally}
  18925.                     dCtlWindow:    WindowPtr;  {pointer to driver's window}
  18926.                     dCtlDelay:     INTEGER;    {number of ticks between }
  18927.                                                { periodic actions}
  18928.                     dCtlEMask:     INTEGER;    {desk accessory event mask}
  18929.                     dCtlMenu:      INTEGER     {menu ID of menu associated
  18930.                                                { with driver}
  18931.                   END;
  18932.  
  18933.       DCtlPtr    = ^DCtlEntry;
  18934.       DCtlHandle = ^DCtlPtr;
  18935.  
  18936. The low-order byte of the dCtlFlags word contains the following flags:
  18937.  
  18938. Bit number    Meaning
  18939.  
  18940.     5         Set if driver is open
  18941.     6         Set if driver is RAM-based
  18942.     7         Set if driver is currently executing
  18943.  
  18944. Assembly-language note:  These flags can be accessed with the global
  18945.                          constants dOpened, dRAMBased, and drvrActive.
  18946.  
  18947. The high-order byte of the dCtlFlags word contains flags copied from the drvrFlags
  18948. word of the driver, as described above.
  18949.  
  18950. DCtlQHdr contains the header of the driver’s I/O queue (described below). DCtlPosition
  18951. is used only by drivers of block devices, and indicates the current source or destination
  18952. position of a Read or Write call. The position is given as a number of bytes beyond
  18953. the physical beginning of the medium used by the device. For example, if one logical
  18954. block of data has just been read from a 3 1/2-inch disk via the Disk Driver, dCtlPosition
  18955. will be 512.
  18956.  
  18957. ROM drivers generally use locations in low memory for their local storage. RAM drivers
  18958. may reserve memory within their code space, or allocate a relocatable block and keep
  18959. a handle to it in dCtlStorage (if the block resides in the application heap, its
  18960. handle will be set to NIL when the heap is reinitialized).
  18961.  
  18962. You can get a handle to a driver’s device control entry by calling the Device Manager
  18963. function GetDCtlEntry.
  18964.  
  18965. FUNCTION GetDCtlEntry (refNum:  INTEGER) :  DCtlHandle; [Not in ROM]
  18966.  
  18967. GetDCtlEntry returns a handle to the device control entry of the device driver having
  18968. the reference number refNum.
  18969.  
  18970. Assembly-language note:  You can get a handle to a driver’s device control
  18971.                          entry from the unit table, as described below.
  18972.  
  18973. _______________________________________________________________________________
  18974.  
  18975. »The Driver I/O Queue
  18976.  
  18977. Each device driver has a driver I/O queue; this is a standard Operating System queue
  18978. (described in the Operating System Utilities chapter) that contains the parameter
  18979. blocks for all asynchronous routines awaiting execution. Each time a routine is
  18980. called, the driver places an entry in the queue; each time a routine is completed,
  18981. its entry is removed from the queue. The queue’s header is located in the dCtlQHdr
  18982. field of the driver’s device control entry. The low-order byte of the queue flags
  18983. field in the queue header contains the version number of the driver, and can be used
  18984. for distinguishing between different versions of the same driver.
  18985.  
  18986. Each entry in the driver I/O queue consists of a parameter block for the routine that
  18987. was called. Most of the fields of this parameter block contain information needed by
  18988. the specific Device Manager routines; these fields are explained above in the section
  18989. “Low-Level Device Manager Routines”. The first four fields of this parameter block,
  18990. shown below, are used by the Device Manager in processing the I/O requests in the
  18991. queue.
  18992.  
  18993. TYPE  ParamBlockRec = RECORD
  18994.                         qLink:      QElemPtr;  {next queue entry}
  18995.                         qType:      INTEGER;   {queue type}
  18996.                         ioTrap:     INTEGER;   {routine trap}
  18997.                         ioCmdAddr:  Ptr;       {routine address}
  18998.                         . . .                  {rest of block}
  18999.                       END;
  19000.  
  19001. QLink points to the next entry in the queue, and qType indicates the queue type,
  19002. which must always be ORD(ioQType). IOTrap and ioCmdAddr contain the trap and address
  19003. of the Device Manager routine that was called.
  19004.  
  19005. _______________________________________________________________________________
  19006.  
  19007. »The Unit Table
  19008.  
  19009. The location of each device control entry is maintained in a list called the unit
  19010. table. The unit table is a 128-byte nonrelocatable block containing 32 four-byte
  19011. entries. Each entry has a number, from 0 to 31, called the unit number, and contains
  19012. a handle to the device control entry for a driver. The unit number can be used as an
  19013. index into the unit table to locate the handle to a specific driver’s device control
  19014. entry; it’s equal to
  19015.  
  19016.   –1 * (refNum + 1)
  19017.  
  19018. where refNum is the driver reference number. For example, the Sound Driver’s reference
  19019. number is –4 and its unit number is 3.
  19020.  
  19021. Figure 3 shows the layout of the unit table with the standard drivers and desk accessories
  19022. installed.
  19023.  
  19024. •••Refer to Figure 3.•••
  19025.  
  19026. Figure 3–The Unit Table
  19027.  
  19028. Warning:  Any new drivers contained in resource files should have resource
  19029.           IDs that don’t conflict with the unit numbers of existing
  19030.           drivers—unless you want an existing driver to be replaced. Be
  19031.           sure to check the unit table before installing a new driver;
  19032.           the base address of the unit table is stored in the global
  19033.           variable UTableBase.
  19034.  
  19035. •••Refer to Technical Note #71:•••
  19036.  
  19037. _______________________________________________________________________________
  19038.  
  19039.  
  19040. æKY Writing…Your…Own…Device…Drivers
  19041. æC »WRITING YOUR OWN DEVICE DRIVERS                              DeviceManager
  19042. _______________________________________________________________________________
  19043.  
  19044. Drivers are usually written in assembly language. The structure of your driver must
  19045. match that shown in the previous section. The routines that do the work of the driver
  19046. should be written to operate the device in whatever way you require. Your driver must
  19047. contain routines to handle Open and Close calls, and may choose to handle Read,
  19048. Write, Control, Status, and KillIO calls as well.
  19049.  
  19050. Warning:  A device driver doesn’t “own” the hardware it operates, and has
  19051.           no way of determining whether another driver is attempting to
  19052.           use that hardware at the same time. There’s a possiblity of
  19053.           conflict in situations where two drivers that operate the same
  19054.           device are installed concurrently.
  19055.  
  19056. When the Device Manager executes a driver routine to handle an application call, it
  19057. passes a pointer to the call’s parameter block in register A0 and a pointer to the
  19058. driver’s device control entry in register A1. From this information, the driver can
  19059. determine exactly what operations are required to fulfill the call’s requests, and do
  19060. them.
  19061.  
  19062. Open and close routines must execute synchronously and return via an RTS instruction.
  19063. They needn’t preserve any registers that they use. Close routines should put a result
  19064. code in register D0. Since the Device Manager sets D0 to 0 upon return from an Open
  19065. call, open routines should instead place the result code in the ioResult field of the
  19066. parameter block.
  19067.  
  19068. The open routine must allocate any private storage required by the driver, store a
  19069. handle to it in the device control entry (in the dCtlStorage field), initialize any
  19070. local variables, and then be ready to receive a Read, Write, Status, Control, or
  19071. KillIO call. It might also install interrupt handlers, change interrupt vectors, and
  19072. store a pointer to the device control entry somewhere in its local storage for its
  19073. interrupt handlers to use. The close routine must reverse the effects of the open
  19074. routine, by releasing all used memory, removing interrupt handlers, and replacing
  19075. changed interrupt vectors. If anything about the operational state of the driver
  19076. should be saved until the next time the driver is opened, it should be kept in the
  19077. relocatable block of memory pointed to by dCtlStorage.
  19078.  
  19079. Prime, control, and status routines must be able to respond to queued calls and
  19080. asynchronous calls, and should be interrupt-driven. Asynchronous portions of the
  19081. routines can use registers A0-A3 and D0-D3, but must preserve any other registers
  19082. used; synchronous portions can use all registers. Prime, control, and status routines
  19083. should return a result code in D0. They must return via an RTS if called immediately
  19084. (with noQueueBit set in the ioTrap field) or if the device couldn’t complete the I/O
  19085. request right away, or via a JMP to the IODone routine (explained below) if not
  19086. called immediately and if the device completed the request.
  19087.  
  19088. Warning:  If the prime, control, and status routines can be called as the
  19089.           result of an interrupt, they must preserve all registers other
  19090.           than A0, A1, and D0-D2. They can’t make any calls to the Memory
  19091.           Manager and cannot depend on unlocked handles being valid. If
  19092.           they use application globals, they must also ensure that register
  19093.           A5 contains the address of the boundary between the application
  19094.           globals and the application parameters; for details, refer to
  19095.           SetCurrentA5 and SetA5 in Macintosh Technical Note #208.
  19096.  
  19097. •••Refer to Technical Note #208:•••
  19098.  
  19099. The prime routine implements Read and Write calls made to the driver. It can distinguish
  19100. between Read and Write calls by comparing the low-order byte of the ioTrap field with
  19101. the following predefined constants:
  19102.  
  19103.   aRdCmd    .EQU    2    ;Read call
  19104.   aWrCmd    .EQU    3    ;Write call
  19105.  
  19106. You may want to use the Fetch and Stash routines (described below) to read and write
  19107. characters. If the driver is for a block device, it should update the dCtlPosition
  19108. field of the device control entry after each read or write.
  19109.  
  19110. The control routine accepts the control information passed to it, and manipulates the
  19111. device as requested. The status routine returns requested status information. Since
  19112. both the control and status routines may be subjected to Control and Status calls
  19113. sending and requesting a variety of information, they must be prepared to respond
  19114. correctly to all types. The control routine must handle KillIO calls. The driver
  19115. identifies KillIO calls by checking the csCode parameter—it will be the global constant
  19116.  
  19117.   killCode    .EQU    1    ;handle the KillIO call
  19118.  
  19119. Warning:  KillIO calls must return via an RTS, and shouldn’t jump
  19120.           (via JMP) to the IODone routine.
  19121.  
  19122. _______________________________________________________________________________
  19123.  
  19124. »Routines for Writing Drivers
  19125.  
  19126. The Device Manager includes three routines—Fetch, Stash, and IODone—that provide
  19127. low-level support for driver routines. These routines can be used only with a pending,
  19128. asynchronous request; include them in the code of your device driver if they’re
  19129. useful to you. A pointer to the device control entry is passed to each of these
  19130. routines in register A1. The device control entry contains the driver I/O queue
  19131. header, which is used to locate the pending request. If there are no pending requests,
  19132. these routines generate the system error dsIOCoreErr (see the System Error Handler
  19133. chapter for more information).
  19134.  
  19135. •••Refer to Technical Notes #36, #108, & 187:•••
  19136. •••Refer to Technical Note #257 & Q & A Stack.•••
  19137.  
  19138. Fetch, Stash, and IODone are invoked via “jump vectors” (stored in the global variables
  19139. JFetch, JStash, and JIODone) rather than macros, in the interest of speed. You use a
  19140. jump vector by moving its address onto the stack. For example:
  19141.  
  19142.   MOVE.L    JIODone,-(SP)
  19143.   RTS
  19144.  
  19145. Fetch and Stash don’t return a result code; if an error occurs, the System Error
  19146. Handler is invoked. IODone may return a result code.
  19147.  
  19148. Fetch function
  19149.  
  19150. Jump vector  JFetch
  19151. On entry     A1:  pointer to device control entry
  19152. On exit      D0:  character fetched; bit 15=1 if it’s the last
  19153.                   character in data buffer
  19154.  
  19155. Fetch gets the next character from the data buffer pointed to by ioBuffer and places
  19156. it in D0. IOActCount is incremented by 1. If ioActCount equals ioReqCount, bit 15 of
  19157. D0 is set. After receiving the last byte requested, the driver should call IODone.
  19158.  
  19159. Stash function
  19160.  
  19161. Jump vector  JStash
  19162. On entry     A1:  pointer to device control entry
  19163.              D0:  character to stash
  19164. On exit      D0:  bit 15=1 if it’s the last character requested
  19165.  
  19166. Stash places the character in D0 into the data buffer pointed to by ioBuffer, and
  19167. increments ioActCount by 1. If ioActCount equals ioReqCount, bit 15 of D0 is set.
  19168. After stashing the last byte requested, the driver should call IODone.
  19169.  
  19170. IODone function
  19171.  
  19172. Jump vector  JIODone
  19173. On entry     A1:  pointer to device control entry
  19174.              D0:  result code (word)
  19175.  
  19176. IODone removes the current I/O request from the driver I/O queue, marks the driver
  19177. inactive, unlocks the driver and its device control entry (if it’s allowed to by the
  19178. dNeedLock bit of the dCtlFlags word), and executes the completion routine (if there
  19179. is one). Then it begins executing the next I/O request in the driver I/O queue.
  19180.  
  19181. Warning:  Due to the way the File Manager does directory lookups, block
  19182.           device drivers should take care to support asynchronous I/O
  19183.           operations. If the driver’s prime routine has completed an
  19184.           asynchronous Read or Write call just prior to calling IODone
  19185.           and its completion routine starts an additional Read or Write,
  19186.           large amounts of the stack may be used (potentially causing the
  19187.           stack to expand into the heap). To avoid this problem, the prime
  19188.           routine should exit via an RTS instruction and then jump to IODone
  19189.           via an interrupt.
  19190.  
  19191.  
  19192. _______________________________________________________________________________
  19193.  
  19194.  
  19195. æKY Interrupts
  19196. æC »INTERRUPTS                                                  DeviceManager
  19197. _______________________________________________________________________________
  19198.  
  19199. This section discusses how interrupts are used on the Macintosh 128K and 512K specifically.
  19200. The general philosophy applies to all Macintosh computers. Only programmers who want
  19201. to write interrupt-driven device drivers need read this section.
  19202.  
  19203. Warning:  Only the Macintosh 128K and 512K are covered in this section.
  19204.           Much of the information presented here is hardware-dependent;
  19205.           programmers are encouraged to write code that’s hardware-independent
  19206.           to ensure compatibility with future versions of the Macintosh.
  19207.  
  19208. An interrupt is a form of exception:  an error or abnormal condition detected by the
  19209. processor in the course of program execution. Specifically, an interrupt is an exception
  19210. that’s signaled to the processor by a device, as distinct from a trap, which arises
  19211. directly from the execution of an instruction. Interrupts are used by devices to
  19212. notify the processor of a change in condition of the device, such as the completion
  19213. of an I/O request. An interrupt causes the processor to suspend normal execution,
  19214. save the address of the next instruction and the processor’s internal status on the
  19215. stack, and execute an interrupt handler.
  19216.  
  19217. The MC68000 recognizes seven different levels of interrupt, each with its own interrupt
  19218. handler. The addresses of the various handlers, called interrupt vectors, are kept in
  19219. a vector table in low memory. Each level of interrupt has its own vector located in
  19220. the vector table. When an interrupt occurs, the processor fetches the proper vector
  19221. from the table, uses it to locate the interrupt handler for that level of interrupt,
  19222. and jumps to the handler. On completion, the handler restores the internal status of
  19223. the processor from the stack and resumes normal execution from the point of suspension.
  19224.  
  19225. There are three devices that can create interrupts:  the Synertek SY6522 Versatile
  19226. Interface Adapter (VIA), the Zilog Z8530 Serial Communications Controller (SCC), and
  19227. the debugging switch. They send a three-bit number called the interrupt priority
  19228. level to the processor. This number indicates which device is interrupting, and which
  19229. interrupt handler should be executed:
  19230.  
  19231.   Level    Interrupting device
  19232.  
  19233.     0      None
  19234.     1      VIA
  19235.     2      SCC
  19236.     3      VIA and SCC
  19237.     4-7    Debugging switch
  19238.  
  19239. A level-3 interrupt occurs when both the VIA and the SCC interrupt at the same instant;
  19240. the interrupt handler for a level-3 interrupt is simply an RTE instruction. Debugging
  19241. interrupts shouldn’t occur during the normal execution of an application.
  19242.  
  19243. The interrupt priority level is compared with the processor priority in bits
  19244. 8-10 of the status register. If the interrupt priority level is greater than the
  19245. processor priority, the MC68000 acknowledges the interrupt and initiates interrupt
  19246. processing. The processor priority determines which interrupting devices are ignored,
  19247. and which are serviced:
  19248.  
  19249.   Level    Services
  19250.  
  19251.     0      All interrupts
  19252.     1      SCC and debugging interrupts only
  19253.     2-6    Debugging interrupts only
  19254.     7      No interrupts
  19255.  
  19256. When an interrupt is acknowledged, the processor priority is set to the interrupt
  19257. priority level, to prevent additional interrupts of equal or lower priority, until
  19258. the interrupt handler has finished servicing the interrupt.
  19259.  
  19260. The interrupt priority level is used as an index into the primary interrupt vector
  19261. table. This table contains seven long words beginning at address $64. Each long word
  19262. contains the starting address of an interrupt handler (see Figure 4).
  19263.  
  19264. Execution jumps to the interrupt handler at the address specified in the table. The
  19265. interrupt handler must identify and service the interrupt. Then it must restore the
  19266. processor priority, status register, and program counter to the values they contained
  19267. before the interrupt occurred.
  19268.  
  19269. •••Refer to Figure 4.•••
  19270.  
  19271. Figure 4–Primary Interrupt Vector Table
  19272.  
  19273. _______________________________________________________________________________
  19274.  
  19275. »Level-1 (VIA) Interrupts
  19276.  
  19277. Level-1 interrupts are generated by the VIA. You’ll need to read the Synertek manual
  19278. describing the VIA to use most of the information provided in this section. The
  19279. level-1 interrupt handler determines the source of the interrupt
  19280. (via the VIA’s interrupt flag register and interrupt enable register) and then uses a
  19281. table of secondary vectors in low memory to determine which interrupt handler to call
  19282. (see Figure 5).
  19283.  
  19284. •••Refer to Figure 5.•••
  19285.  
  19286. Figure 5–Level-1 Secondary Interrupt Vector Table
  19287.  
  19288. The level-1 secondary interrupt vector table is stored in the global variable Lvl1DT.
  19289. Each vector in the table points to the interrupt handler for a different source of
  19290. interrupt. The interrupts are handled in order of their entry in the table, and only
  19291. one interrupt handler is called per level-1 interrupt (even if two or more sources
  19292. are interrupting). This allows the
  19293. level-1 interrupt handler to be reentrant; interrupt handlers should lower the processor
  19294. priority as soon as possible in order to enable other pending interrupts to be processed.
  19295.  
  19296. The one-second interrupt updates the global variable Time (explained in the Operating
  19297. System Utilities chapter); it’s also used for inverting (“blinking”) the apple symbol
  19298. in the menu bar when the alarm goes off. Vertical retrace interrupts are generated
  19299. once every vertical retrace interval; control is passed to the Vertical Retrace
  19300. Manager, which performs recurrent system tasks
  19301. (such as updating the global variable Ticks) and executes tasks installed by the
  19302. application. (For more information, see the Vertical Retrace Manager chapter.)
  19303.  
  19304. If the cumulative elapsed time for all tasks during a vertical retrace interrupt
  19305. exceeds about 16 milliseconds (one video frame), the vertical retrace interrupt may
  19306. itself be interrupted by another vertical retrace interrupt. In this case, tasks to
  19307. be performed during the second vertical retrace interrupt are ignored, with one
  19308. exception:  The global variable Ticks will still be updated.
  19309.  
  19310. The shift-register interrupt is used by the keyboard and mouse interrupt handlers.
  19311. Whenever the Disk Driver or Sound Driver isn’t being used, you can use the T1 and T2
  19312. timers for your own needs; there’s no way to tell, however, when they’ll be needed
  19313. again by the Disk Driver or Sound Driver.
  19314.  
  19315. The base address of the VIA (stored in the global variable VIA) is passed to each
  19316. interrupt handler in register A1.
  19317.  
  19318. _______________________________________________________________________________
  19319.  
  19320. »Level-2 (SCC) Interrupts
  19321.  
  19322. Level-2 interrupts are generated by the SCC. You’ll need to read the Zilog manual
  19323. describing the SCC to effectively use the information provided in this section. The
  19324. level-2 interrupt handler determines the source of the interrupt, and then uses a
  19325. table of secondary vectors in low memory to determine which interrupt handler to call
  19326. (see Figure 6).
  19327.  
  19328. •••Refer to Figure 6.•••
  19329.  
  19330. Figure 6–Level-2 Secondary Interrupt Vector Table
  19331.  
  19332. The level-2 secondary interrupt vector table is stored in the global variable Lvl2DT.
  19333. Each vector in the table points to the interrupt handler for a different source of
  19334. interrupt. The interrupts are handled according to the following fixed priority:
  19335.  
  19336.   channel A receive character available and special receive
  19337.   channel A transmit buffer empty
  19338.   channel A external/status change
  19339.   channel B receive character available and special receive
  19340.   channel B transmit buffer empty
  19341.   channel B external/status change
  19342.  
  19343. Only one interrupt handler is called per level-2 interrupt (even if two or more
  19344. sources are interrupting). This allows the level-2 interrupt handler to be reentrant;
  19345. interrupt handlers should lower the processor priority as soon as possible in order
  19346. to enable other pending interrupts to be processed.
  19347.  
  19348. External/status interrupts pass through a tertiary vector table in low memory to
  19349. determine which interrupt handler to call (see Figure 7).
  19350.  
  19351. •••Refer to Figure 7.•••
  19352.  
  19353. Figure 7–Level-2 External/Status Interrupt Vector Table
  19354.  
  19355. The external/status interrupt vector table is stored in the global variable ExtStsDT.
  19356. Each vector in the table points to the interrupt handler for a different source of
  19357. interrupt. Communications interrupts (break/abort, for example) are always handled
  19358. before mouse interrupts.
  19359.  
  19360. When a level-2 interrupt handler is called, D0 contains the address of the SCC read
  19361. register 0 (external/status interrupts only), and D1 contains the bits of read register
  19362. 0 that have changed since the last external/status interrupt. A0 points to the SCC
  19363. channel A or channel B control read address and A1 points to SCC channel A or channel
  19364. B control write address, depending on which channel is interrupting. The SCC’s data
  19365. read address and data write address are located four bytes beyond A0 and A1, respectively;
  19366. they’re also contained in the global variables SCCWr and SCCRd. You can use the
  19367. following predefined constants as offsets from these base addresses to locate the SCC
  19368. control and data lines:
  19369.  
  19370.   aData   .EQU    6    ;channel A data in or out
  19371.   aCtl    .EQU    2    ;channel A control
  19372.   bData   .EQU    4    ;channel B data in or out
  19373.   bCtl    .EQU    0    ;channel B control
  19374.  
  19375. _______________________________________________________________________________
  19376.  
  19377. »Writing Your Own Interrupt Handlers
  19378.  
  19379. You can write your own interrupt handlers to replace any of the standard interrupt
  19380. handlers just described. Be sure to place a vector that points to your interrupt
  19381. handler in one of the vector tables.
  19382.  
  19383. Both the level-1 and level-2 interrupt handlers preserve registers A0-A3 and
  19384. D0-D3. Every interrupt handler (except for external/status interrupt handlers) is
  19385. responsible for clearing the source of the interrupt, and for saving and restoring
  19386. any additional registers used. Interrupt handlers should return directly via an RTS
  19387. instruction, unless the interrupt is completing an asynchronous call, in which case
  19388. they should jump (via JMP) to the IODone routine.
  19389.  
  19390. _______________________________________________________________________________
  19391.  
  19392.  
  19393. æKY The…Chooser
  19394. æC »THE CHOOSER                                                 DeviceManager
  19395. _______________________________________________________________________________
  19396.  
  19397. Note:  The extensions to the Device Manager described in the following
  19398.        section were originally documented in Inside Macintosh, Volume IV.
  19399.        As such, this information refers to the 128K ROMs and System file
  19400.        version 3.2 and later.
  19401.  
  19402. The Chooser is a desk accessory that provides a standard interface to help solicit
  19403. and accept specific choices from the user. It allows new device drivers to prompt the
  19404. user for choices such as which serial port to use, which AppleTalk zone to communicate
  19405. with, and which LaserWriter to use.
  19406.  
  19407. The Chooser relies heavily on the List Manager for creating, displaying, and manipulating
  19408. possible user selections. The List Manager is described in the List Manager chapter.
  19409.  
  19410. Under the Chooser, each device is represented by a device resource file in the system
  19411. folder on the user’s system startup disk. (This is an extension of the concept of
  19412. printer resource files, described in the Printing Manager chapter.) The Chooser
  19413. accepts three types of device resource files to identify different kinds of devices:
  19414.  
  19415.   File type    Device type
  19416.  
  19417.   'PRES'       Serial printer
  19418.   'PRER'       Non-serial printer
  19419.   'RDEV'       Other device
  19420.  
  19421. The creator of each file is left undefined, allowing each device to have its own
  19422. icon.
  19423.  
  19424. In addition to any actual driver code, each device resource file of type 'PRER' or
  19425. 'RDEV' contains a set of resources that tell the Chooser how to handle the device.
  19426. These resources include:
  19427.  
  19428.   Resource type    Resource ID    Description
  19429.  
  19430.   'PACK'             –4096        Device package (described below)
  19431.   'STR '             –4096        Type name for AppleTalk devices
  19432.   'GNRL'             –4096        NBP timeout and retry information
  19433.                                   for AppleTalk devices
  19434.   'STR '             –4093        Left button title
  19435.   'STR '             –4092        Right button title
  19436.   'STR '             –4091        String for Chooser to use to label
  19437.                                   the list when choosing the device
  19438.   'BNDL'                          Icon information
  19439.   'STR '             –4090        Reserved for use by the Chooser
  19440.  
  19441. Warning:  You should give your device type a distinctive icon, since this
  19442.           may be the only way that devices are identified in the Chooser’s
  19443.           screen display.
  19444.  
  19445. Device resource files of type 'PRES' (serial printers) contain only the driver code,
  19446. without any of the resources listed above. The configuration of such devices is
  19447. implemented entirely by the Chooser.
  19448.  
  19449. _______________________________________________________________________________
  19450.  
  19451. »The Device Package
  19452.  
  19453. The device package is usually written in assembly language, but may be written partially
  19454. in Pascal. The assembly-language structure of the 'PACK' –4096 resource is as follows:
  19455.  
  19456.   Offset (hex)    Word
  19457.  
  19458.       0           BRA.S to offset $10
  19459.       2           Device ID (word)
  19460.       4           'PACK' (long word)
  19461.       8           $F000 (–4096)
  19462.       A           Version (word)
  19463.       C           Flags (long word)
  19464.       10          Start of driver code
  19465.  
  19466. The device ID is an integer that identifies the device. The version word differentiates
  19467. versions of the driver code. The flags field contains the following information:
  19468.  
  19469.   Bit    Meaning
  19470.  
  19471.   31     Set if an AppleTalk device
  19472.   30–29  Reserved (clear to 0)
  19473.   28     Set if device package can have multiple instances selected at once
  19474.   27     Set if device package uses left button
  19475.   26     Set if device package uses right button
  19476.   25     Set if no saved zone name
  19477.   24     Set if device package uses actual zone names
  19478.   23–17  Reserved (clear to 0)
  19479.   16     Set if device package accepts the newSel message
  19480.   15     Set if device package accepts the fillList message
  19481.   14     Set if device package accepts the getSel message
  19482.   13     Set if device package accepts the select message
  19483.   12     Set if device package accepts the deselect message
  19484.   11     Set if device package accepts the terminate message
  19485.   10–0   Reserved (clear to 0)
  19486.  
  19487. _______________________________________________________________________________
  19488.  
  19489. »Communication with the Chooser
  19490.  
  19491. The Chooser communicates with device packages as if they were the following function:
  19492.  
  19493. FUNCTION Device (message,caller:  INTEGER; objName,zoneName:  StringPtr;
  19494.                  p1,p2:  LONGINT) :  OSErr;
  19495.  
  19496. The message parameter identifies the operation to be performed. It has one of the
  19497. following values:
  19498.  
  19499. CONST  newSelMsg    = 12;   {new user selections have been made}
  19500.        fillListMsg  = 13;   {fill the list with choices to be made}
  19501.        getSelMsg    = 14;   {mark one or more choices as selected}
  19502.        selectMsg    = 15;   {a choice has actually been made}
  19503.        deselectMsg  = 16;   {a choice has been cancelled}
  19504.        terminateMsg = 17;   {lets device package clean up}}
  19505.        buttonMsg    = 19;   {tells driver a button has been selected}
  19506.  
  19507. The device package should always return noErr, except with select and deselect; with
  19508. these messages, a result code other than noErr prevents selection or deselection from
  19509. occurring. The device package must ignore any other messages in the range 0..127 and
  19510. return noErr. If the message is selectMsg or deselectMsg, it may not call the List
  19511. Manager.
  19512.  
  19513. The caller parameter identifies the caller as the Chooser, with a value of 1. Values
  19514. in the range 0..127 are reserved; values outside this range may be used by applications.
  19515.  
  19516. For AppleTalk devices, the zoneName parameter is a pointer to a string of up to 32
  19517. characters containing the name of the AppleTalk zone in which the devices can be
  19518. found. If the Chooser is being used with the local zone and bit 24 of the Flags field
  19519. of the 'PACK' –4096 resource is clear, the string value is '*'; otherwise it’s the
  19520. actual zone name.
  19521.  
  19522. The p1 parameter is a handle to a List Manager list of choices for a particular
  19523. device; this device list must be filled by the device package in response to the
  19524. fillListMsg message.
  19525.  
  19526. Other details of the Chooser messages and their parameters are given below.
  19527.  
  19528. »The NewSelMsg Parameter
  19529.  
  19530. The Chooser sends the newSel message (instead of the select or deselect message) only
  19531. to device packages that allow multiple selections, when the user changes the selection.
  19532.  
  19533. The objName and p2 parameters are not used.
  19534.  
  19535. »The FillListMsg Parameter
  19536.  
  19537. When the Chooser sends the fillList message, the device package should fill a List
  19538. Manager list filled with choices for a particular device; the p1 parameter is a
  19539. handle to this list.
  19540.  
  19541. The objName and p2 parameters are not used.
  19542.  
  19543. »The GetSelMsg Parameter
  19544.  
  19545. When the Chooser sends the getSel message the device package should mark one or more
  19546. choices in the given list as currently selected, by a call to LSetSelect.
  19547.  
  19548. The objName and p2 parameters are not used.
  19549.  
  19550. »The SelectMsg Parameter
  19551.  
  19552. The Chooser sends the select message whenever a particular choice has become selected,
  19553. but only to device packages that do not allow multiple selections. The device package
  19554. may not call the List Manager.
  19555.  
  19556. If the device accepts fillList messages, objName is undefined. Otherwise, the objName
  19557. parameter is a pointer to a string of up to 32 characters containing the name of the
  19558. device.
  19559.  
  19560. If the device accepts fillList messages, p2 gives the row number of the list that has
  19561. become selected; otherwise (if the device is an AppleTalk device) p2 gives the AddrBlock
  19562. value for the address of the AppleTalk device that has just become selected.
  19563.  
  19564. »The DeselectMsg Parameter
  19565.  
  19566. The Chooser sends the deselect message whenever a particular choice has become deselected,
  19567. but only to device packages that do not allow multiple selections. The device package
  19568. may not call the List Manager.
  19569.  
  19570. If the device accepts fillList messages, objName is undefined. Otherwise, the objName
  19571. parameter is a pointer to a string of up to 32 characters containing the name of the
  19572. device.
  19573.  
  19574. If the device accepts fillList messages, p2 gives the row number of the list that has
  19575. become deselected; otherwise (if the device is an AppleTalk device) p2 gives the
  19576. AddrBlock value for the address of the AppleTalk device that has just become deselected.
  19577.  
  19578. »The TerminateMsg Parameter
  19579.  
  19580. The Chooser sends the terminate message when the user selects a different device
  19581. icon, closes the Chooser window, or changes zones. It allows the device package to
  19582. perform cleanup tasks, if necessary. The device package should not dispose of the
  19583. device list.
  19584.  
  19585. The objName and p2 parameters are not used.
  19586.  
  19587. »The ButtonMsg Parameter
  19588.  
  19589. The Chooser sends the button message when a button in the Chooser display has been
  19590. clicked.
  19591.  
  19592. The low-order byte of the p2 parameter has a value of 1 if the left button has been
  19593. clicked and 2 if the right button has been clicked.
  19594.  
  19595. The objName parameter is not used.
  19596.  
  19597. _______________________________________________________________________________
  19598.  
  19599. »Operation of the Chooser
  19600.  
  19601. When the Chooser is first selected from the desk accessory menu, it searches the
  19602. system folder of the startup disk for device resource files—that is, resource files
  19603. of type 'PRER', 'PRES', or 'RDEV'. For each one that it finds, it opens the file,
  19604. fetches the device’s icon, fetches the flags long word from the device package, and
  19605. closes the file. The Chooser then takes the following actions for each device, based
  19606. on the information just retrieved:
  19607.  
  19608.   •  It displays the device’s icon in the Chooser’s window.
  19609.   •  If the device is an AppleTalk device and AppleTalk is not connected,
  19610.      the Chooser grays the device’s icon.
  19611.  
  19612. When the user selects a device icon that is not grayed, the Chooser reopens the
  19613. corresponding device resource file. It then does the following:
  19614.  
  19615.   •  If the device is type 'PRER' or 'PRES', it sets the current
  19616.      printer type to that device.
  19617.  
  19618.   •  It labels the device’s list box with the string in the resource
  19619.      'STR ' with an ID of –4091.
  19620.  
  19621.   •  If the device is a local printer, the Chooser fills its list box
  19622.      with the two icons for the printer port and modem port serial drivers.
  19623.      Later it will record the user’s choice in low memory and parameter RAM.
  19624.  
  19625.   •  If the device accepts fillList messages, the Chooser calls the device
  19626.      package, which should fill column 0 of the list pointed to by p1 with
  19627.      the names (without length bytes) of all available devices in the zone.
  19628.  
  19629.   •  If the device is an AppleTalk device that does not accept fillList
  19630.      messages, the Chooser initiates an asynchronous routine that interrogates
  19631.      the current AppleTalk zone for all devices of the type specified in the
  19632.      device’s resource 'STR ' –4096. The NBP retry interval and count are
  19633.      taken from the 'GNRL' resource –4096; the format of this resource
  19634.      consists one byte for the interval followed by another byte for the
  19635.      count. As responses arrive, the Chooser updates the list box.
  19636.  
  19637.   •  To determine which list choices should be currently selected, the
  19638.      Chooser calls the device with the getSel message. The device code
  19639.      should respond by inspecting the list and setting the selected/unselected
  19640.      state of each entry. The Chooser may make this call frequently; for
  19641.      example, each time a new response to the AppleTalk zone interrogation
  19642.      arrives. Hence the device should alter only those entries that need
  19643.      changing. This procedure is not used with serial printers; for them,
  19644.      the Chooser just accesses low memory.
  19645.  
  19646.   •  The Chooser checks the flag in the 'PACK' –4096 resource that indicates
  19647.      whether multiple devices can be active at once, and sets List Manager
  19648.      bits accordingly. Whenever the user selects or deselects a device, the
  19649.      Chooser will call the device package with the appropriate message (if
  19650.      it’s accepted). For packages that do not accept multiple active devices,
  19651.      this is the select or deselect message; otherwise it’s the newSel message.
  19652.      The device code should implement both mounting and unmounting the device,
  19653.      if appropriate, and recording the user’s selections on disk, preferably
  19654.      in the device resource file (which is the current resource file).
  19655.  
  19656. When the Chooser is deactivated, it calls the UpdateResFile procedure on the device
  19657. resource file and flushes the system startup volume.
  19658.  
  19659. When the user chooses a different device type icon or closes the Chooser, the Chooser
  19660. will call the device with the terminate message (if it’s accepted). This allows
  19661. device packages to clean up, if necessary. After this check, the Chooser closes the
  19662. device resource file (if the device is not the current printer) and flushes the
  19663. system startup volume.
  19664.  
  19665. _______________________________________________________________________________
  19666.  
  19667. »Writing a Device Driver to Run Under Chooser
  19668.  
  19669. The code section of a driver running under chooser is contained in the 'PACK'
  19670. –4096 resource, as explained earlier. The driver structure remains as described
  19671. earlier in this chapter.
  19672.  
  19673. Device packages initially have no data space allocated. There are two ways to acquire
  19674. data space for a device package:
  19675.  
  19676.   •  Use the List Manager
  19677.   •  Create a resource
  19678.  
  19679. These options are discussed below.
  19680.  
  19681. The best method is to call the List Manager. The Chooser uses column 0 of the device
  19682. list to store the names displayed in the list box. If the device package currently in
  19683. use does not accept fillList messages, column 1 stores the four-byte AppleTalk internet
  19684. addresses of the entities in the list. Therefore, the device package can use column 1
  19685. and higher (if it accepts fillList) or column 2 and higher to store data private to
  19686. itself. The standard List Manager calls can be used to add these columns, place data
  19687. in them, and retrieve data stored there.
  19688.  
  19689. •••Refer to Technical Note #250:•••
  19690.  
  19691. There are several restrictions on data storage in List Manager cells. The list is
  19692. disposed whenever :
  19693.  
  19694.   •  the user changes device types.
  19695.   •  the user changes the current zone.
  19696.   •  the device package does not accept fillList messages, and a new
  19697.      response to the AppleTalk zone interrogation arrives. The device
  19698.      package will be called with the getSel message immediately afterwards.
  19699.  
  19700. When either of the first two situations occurs, the device package is called with the
  19701. terminate message before the list is disposed.
  19702.  
  19703. Another way to get storage space is to create a resource in the device’s file. This
  19704. file is always the current resource file when the package is called; therefore it can
  19705. issue GetResource calls to get a handle to its storage.
  19706.  
  19707. It is important for most device packages to record which devices have been chosen. To
  19708. do this, the recommended method is to create a resource in the resource file. This
  19709. resource can be of any type; it fact, it’s advantageous to provide your own resource
  19710. type so that no other program will try to access it. If you choose to use a standard
  19711. resource type, you should use only resource IDs in the range –4080 to –4065.
  19712.  
  19713.  
  19714. Note:  The extensions to the Device Manager described in the following
  19715.        paragraphs were originally documented in Inside Macintosh, Volume V.
  19716.        As such, this information refers to the Macintosh SE and Macintosh II
  19717.        ROMs and System file version 4.1 and later.
  19718.  
  19719. _______________________________________________________________________________
  19720.  
  19721. »Chooser Changes
  19722.  
  19723. Note:  The extensions to the Device Manager described in the following
  19724.        paragraphs were originally documented in Inside Macintosh, Volume V.
  19725.        As such, this information refers to the Macintosh SE and Macintosh II
  19726.        ROMs and System file version 4.1 and later.
  19727.  
  19728. Three new facilities for user-written device packages have been added to the Chooser:
  19729.  
  19730.   •  In addition to specifying and setting their names, a device package
  19731.      can now position one or both buttons.
  19732.   •  A device package can now supply a custom list definition for the
  19733.      device list.  The custom list can include icons, pictures, or small
  19734.      icons next to the name.
  19735.   •  Applications that do their own housekeeping can now bypass the
  19736.      warning message brought up whenever a different device is chosen.
  19737.  
  19738. Figure 8 shows the new window displayed by the Chooser.
  19739.  
  19740. •••Refer to Figure 8.•••
  19741.  
  19742. Figure 8–The Chooser Window
  19743.  
  19744. As described elsewhere in this chapter, the Chooser can also prompt the user for
  19745. which AppleTalk network zone to communicate with.  See Figure 9.
  19746.  
  19747. •••Refer to Figure 9.•••
  19748.  
  19749. Figure 9–The Chooser Displaying Zones
  19750.  
  19751. »Buttons
  19752.  
  19753. A device package can choose to have 0, 1, or 2 buttons, as determined by bits 27 and
  19754. 26 in the flag field of the device ID.  The two buttons are not the same. The button
  19755. set by bit 27 is called the Left Button, and the button set by bit 26 the Right
  19756. Button, because these are their default positions.
  19757.  
  19758. The Left Button has a double border, and if it is highlighted (the title string is
  19759. dark, not gray), then a Return, Enter, or double click are equivalent to clicking the
  19760. button.  The Left Button is highlighted only when one or more devices are selected in
  19761. the device list.  The Right Button has a single border, never dims its title, and can
  19762. be activated only by clicking it.
  19763.  
  19764. Buttons can be positioned by having  a resource type 'nrct' with an ID of –4096 in
  19765. the device file.  The first word of the resource is the number of rectangles in the
  19766. list, in this case two; the rest of the resource contains the rectangle definitions. 
  19767. The first rectangle is the Left Button, the second is the Right Button.
  19768.  
  19769. Each rectangle definition is eight bytes long and contains the rectangle coordinates
  19770. in the order [top, left, bottom, right] order. The default values are [112, 206, 132,
  19771. 266] for the Left Button, and [112, 296, 132, 356] for the Right Button.  Substituting
  19772. 'nrct' values of [112, 251, 132, 311], for example, would center a single button.
  19773.  
  19774. There’s an additional button-related change:  in the ButtonMsg parameter, the low
  19775. order byte of the P2 parameter has a value of 1 or 2 depending on whether the Left
  19776. Button or Right Button was clicked.  The high order word of P2 now contains modifier
  19777. bits from the event.
  19778. _______________________________________________________________________________
  19779.  
  19780. »List Definition Procedure
  19781.  
  19782. The Chooser uses the List Manager to produce and display the standard device list. 
  19783. The programmer can now supply a list definition procedure, which could, for example,
  19784. include pictures or icons.  The application should provide an
  19785. 'LDEF' resource with an ID of –4096.
  19786.  
  19787. Also, with Chooser 3.0 and above the device may use the refCon field of the device
  19788. list for its own purposes.  Remember that the list will be disposed of whenever the
  19789. user changes device types or changes the current zone.
  19790.  
  19791. Before the list is disposed of, the device package will be called with the terminate
  19792. message.
  19793.  
  19794. See the List Manager chapter for the mechanics of list construction and the list
  19795. record data structure.
  19796.  
  19797. »Page Setup
  19798.  
  19799. The Chooser normally issues a warning message whenever a different printer type is
  19800. selected:
  19801.  
  19802.     Be sure to choose Page Setup and confirm the settings so that
  19803.     the application can format documents correctly for the  <printer>.
  19804.  
  19805. Since some applications handle the page resetup correctly on their own, the Chooser
  19806. now offers a way for applications to bypass the message.
  19807.  
  19808. FUNCTION SetChooserAlert (f:BOOLEAN) : BOOLEAN;
  19809.  
  19810. If f is true, the Chooser will put up the page setup alert; if f is false it won’t. 
  19811. SetChooserAlert returns the original alert state.  The application should restore the
  19812. original alert state when it exits.
  19813.  
  19814. Assembly-language note:  If the psAlert bit of the low-memory global
  19815.                          HiliteMode is 0 then no page setup alert will be
  19816.                          generated.  Applications that set or clear this
  19817.                          bit must be sure not to affect any other bits in
  19818.                          the byte and to restore the bit as they leave.
  19819.  
  19820.                            HiliteMode  equ   $938
  19821.                            psAlert     equ   6
  19822.                            bclr        #psAlert,HiliteMode
  19823.                            bset        #psAlert,HiliteMode
  19824.  
  19825. »Device Package Function
  19826.  
  19827. When the device package is called, the device file will be the current resource file,
  19828. the Chooser’s window will be the current grafPort, and the System Folder of the
  19829. current startup disk will be the default volume.  The device package must preserve
  19830. all of these.
  19831.  
  19832. _______________________________________________________________________________
  19833.  
  19834.  
  19835. æKY The…Startup…Process
  19836. æC »THE STARTUP PROCESS                                         DeviceManager
  19837. _______________________________________________________________________________
  19838.  
  19839. Note:  The extensions to the Device Manager described in the following
  19840.        sections were originally documented in Inside Macintosh, Volume V.
  19841.        As such, this information refers to the Macintosh SE and Macintosh II
  19842.        ROMs and System file version 4.1 and later.
  19843.  
  19844. The Macintosh II ROM searches for the startup device using an algorithm described in
  19845. the Start Manager chapter. It will attempt to start from a NuBus card only when
  19846. certain values are set in its parameter RAM.  These values can be accessed by using
  19847. Start Manager routines.
  19848.  
  19849. When the Macintosh starts up from a card in a NuBus slot, it uses startup code found
  19850. in an sResource in the configuration ROM on the card.  Otherwise, the normal Macintosh
  19851. startup process occurs.  Configuration ROMs and sResources are described in the Slot
  19852. Manager chapter and in the book “Designing Cards and Drivers for Macintosh II and
  19853. Macintosh SE.”
  19854.  
  19855. If parameter RAM specifies a valid sResource ID and slot, and if that sResource has
  19856. an sBootRecord, it is used for startup.  The ROM loads the slot startup code into
  19857. memory and calls its entry point to execute it.  For non-Macintosh operating systems
  19858. that take over the machine, this code is either the operating system itself or a
  19859. startup program.  For instance, a traditional UNIX® startup process would bring in
  19860. the secondary startup program, which prompts for a device name or filename to execute.
  19861.  The ROM would never receive control again.
  19862.  
  19863. The sBootRecord code is first called early in the ROM-based startup sequence, before
  19864. any access to the internal drive.  It is passed an seBlock pointed to by register A0.
  19865.  If a non-Macintosh operating system is being installed, the sBootRecord can pass
  19866. control to it.  In this case, control never returns to the normal start sequence in
  19867. the Macintosh ROM.
  19868.  
  19869. When the Macintosh operating system is started up, the sBootRecord is called twice. 
  19870. The first time, when the value of seBootState is 0, the startup code tries to load
  19871. and open at least one driver for the card-based device and install it in the disk
  19872. drive queue.  It returns the refnum of the driver.  That driver becomes the initial
  19873. one used to install the Macintosh operating system.  During the second call to the
  19874. sBootRecord (when the value of seBootState is 1), which happens after system patches
  19875. have been installed but before 'INIT' resources have been executed, the sBootRec must
  19876. open any remaining drivers for devices on the card.
  19877.  
  19878. The sBootRecord can use the HOpen call to open the driver and install it into the
  19879. unit table.  The HOpen call will either fetch the driver from the sDriver directory,
  19880. or call the sLoadDriver record if one exists.  In any case, the driver’s open code
  19881. must install the driver into the drive queue.  This process is discussed in more
  19882. detail in the Card Firmware chapter of the book “Designing Cards and Drivers for
  19883. Macintosh II and Macintosh SE.”
  19884.  
  19885. _______________________________________________________________________________
  19886.  
  19887. »Automatic Driver Installation
  19888.  
  19889. During the startup process the system installs the default video and startup drivers,
  19890. as described in the Start Manager chapter.  Immediately prior to installing the
  19891. 'INIT' resources, the system searches the NuBus slots looking for other device drivers
  19892. to install.  The sRsrcDir data structure in each
  19893. card’s configuration ROM describes all devices on that card.  For each device there
  19894. is a sRsrcList structure which contains the resource name (sRsrcName) and the offset
  19895. to a table of drivers.  These structures are described in the Slot Manager chapter.
  19896.  
  19897. For each sResource, the search for drivers during startup takes place in the following
  19898. steps:
  19899.  
  19900.   1.  The operating system looks for an sRsrc_Flags field in the sResource list.
  19901.  
  19902.   2.  If no sRsrc_Flags field exists, or if an sRsrc_Flags field exists and
  19903.       the field’s fOpenAtStart bit is set to 1, the operating system searches
  19904.       for a driver, as described below in steps 3 and 4.  If the value of
  19905.       fOpenAtStart is 0, the operating system does not search for a driver;
  19906.       it goes on to the next sResource.
  19907.  
  19908.   3.  The system searches the sResource list for a driver load record
  19909.       (sRsrc_LoadRec)— a routine designed to copy a driver into the Macintosh
  19910.       system heap.  If such a routine exists, the system copies it from the
  19911.       card’s ROM to the heap and executes it.  The system passes this routine
  19912.       a pointer in A0 to an seBlock; on exit, the routine must return a handle
  19913.       in the seResult field of the same seBlock to the driver it has loaded.
  19914.       If the value of the seStatus field is 0, the system then installs the
  19915.       new driver.
  19916.  
  19917.   4.  If there is no driver load record, the system searches the sResource
  19918.       list for a driver directory entry (sRsrc_DrvrDir).  If there is such
  19919.       an entry and the directory contains a driver of the type sMacOS68000
  19920.       or sMacOS68020, the system reads the driver from the card’s ROM and
  19921.       installs it in the Macintosh system heap.
  19922.  
  19923. To install a driver, the Macintosh II ROM first loads it into the system heap and
  19924. locks it if the dNeedsLock bit in the driver flags (drvrFlags) word is set. It then
  19925. installs the driver with a DrvrInstall system call and initializes it with an Open
  19926. call. If the driver returns an error from the Open call, it is marked closed, the
  19927. refNum field is cleared in the ioParameter block, and the driver is unlocked. Note
  19928. that this procedure guarantees that driver initialization code will be executed
  19929. before the system starts executing applications.
  19930.  
  19931. The video driver used at the beginning of system startup (the one that makes the
  19932. “happy Macintosh” appear) must be taken from a video card’s configuration ROM because
  19933. the System file is not yet accessible.  If a system contains multiple video cards,
  19934. the one used first is determined by parameter RAM or, by default, by selecting the
  19935. lowest slot number.  To override this initial driver, the user must install an 'INIT'
  19936. 31 resource that explicitly closes the driver from the configuration ROM and loads a
  19937. new driver from a file.
  19938.  
  19939. The unit table data structure has been extended from 48 devices to 64 to accommodate
  19940. installing slot devices.  If more than 64 entries are needed, the table automatically
  19941. expands up to a maximum of 128 entries.
  19942.  
  19943. When a driver serves a device that is plugged into a NuBus slot, it needs to know the
  19944. slot number, the sResource ID number and the ExtDevID number. These numbers are
  19945. discussed in the Slot Manager chapter. The Slot Manager provides values for five new
  19946. entries on the end of the Device Control Entry (DCE) data structure for each sResource.
  19947.  These new entries are
  19948.  
  19949.   •  a byte containing the slot number (dCtlSlot)
  19950.   •  a byte containing the RsrcDir ID number for the sResource (dCtlSlotID)
  19951.   •  a pointer for the driver to use for the device base address (dCtlDevBase)
  19952.   •  a reserved field for future use
  19953.   •  a byte containing the external device ID (dCtlExtDev)
  19954.  
  19955. The Device Control Entry now looks like this:
  19956.  
  19957.   AuxDCE = PACKED RECORD
  19958.              dCtlDriver:    Ptr;      {ptr to ROM or handle to RAM driver}
  19959.              dCtlFlags:     INTEGER;  {flags}
  19960.              dCtlQHdr:      QHdr;     {driver's i/o queue}
  19961.              dCtlPosition:  LONGINT;  {byte pos used by read and write calls}
  19962.              dCtlStorage:   Handle;   {hndl to RAM drivers private storage}
  19963.              dCtlRefNum:    INTEGER;  {driver's reference number}
  19964.              dCtlCurTicks:  LONGINT;  {counter for timing system task calls}
  19965.              dCtlWindow:    Ptr;      {ptr to driver's window if any}
  19966.              dCtlDelay:     INTEGER;  {number of ticks btwn sysTask calls}
  19967.              dCtlEMask:     INTEGER;  {desk acessory event mask}
  19968.              dCtlMenu:      INTEGER;  {menu ID of menu associated with driver}
  19969.              dCtlSlot:      Byte;     {slot}
  19970.              dCtlSlotId:    Byte;     {slot ID}
  19971.              dCtlDevBase:   LONGINT;  {base address of card for driver}
  19972.              reserved:      LONGINT;  {reserved; should be 0}
  19973.              dCtlExtDev:    Byte;     {external device ID}
  19974.              fillByte:      Byte;     {reserved}
  19975.            END; {SlotDCE}
  19976.   AuxDCEPtr    = ^AuxDCE;
  19977.   AuxDCEHandle = ^AuxDCEPtr;
  19978.  
  19979. All Device Control Entries are set before the driver’s Open routine is called.
  19980.  
  19981. Use of the base address pointer dCtlDevBase in the DCE is optional.  On a card with
  19982. multiple instances of the same device, the driver can use this pointer to distinguish
  19983. between devices.  Because the DCE address is passed to the driver on every call from
  19984. the Device Manager, the presence of this pointer in the DCE simplifies location of
  19985. the correct device.  This pointer is the address of the base of the card’s slot space
  19986. plus an optional offset obtained from the MinorBaseOS field of the sResource.  This
  19987. field frees the driver writer from the necessity of locating the hardware for simple
  19988. slot devices.  The system makes no other references to it.
  19989.  
  19990. _______________________________________________________________________________
  19991.  
  19992.  
  19993. æKY Opening…Slot…Devices
  19994. æC »OPENING SLOT DEVICES                                        DeviceManager
  19995. _______________________________________________________________________________
  19996.  
  19997. The low-level PBOpen routine has been extended to let you open devices in NuBus
  19998. slots. A new call has been defined:  OpenSlot is the equivalent of PBOpen except that
  19999. it sets the IMMED bit, which signals an extended parameter block.
  20000.  
  20001. FUNCTION OpenSlot(paramBlock: paramBlkPtr; aSync: BOOLEAN) : OsErr;
  20002.  
  20003. If the slot sResource serves a single device (for example, a video device), clear all
  20004. the bits of the ioFlags field and use the following parameter block:
  20005.  
  20006. Parameter block
  20007.   -->    12    ioCompletion  pointer
  20008.   <--    16    ioResult      word
  20009.   -->    18    ioNamePtr     pointer
  20010.   <--    22    ioRefNum      word
  20011.   -->    27    ioPermssn     byte
  20012.  
  20013.   -->    28    ioMix         pointer
  20014.   -->    32    ioFlags       word
  20015.   -->    34    ioSlot        byte
  20016.   -->    35    ioId          byte
  20017.  
  20018. In the extension fields, ioMix is a pointer reserved for use by the driver open
  20019. routine.  The ioSlot parameter contains the slot number of the device being opened,
  20020. in the range 9..$E; if a built-in device is being opened, ioSlot must be 0.  The ioId
  20021. parameter contains the sResource ID.  Slot numbers and sResources are discussed in
  20022. the Slot Manager.
  20023.  
  20024. If the slot sResource serves more than one device (for example, a chain of disk
  20025. drives), set the fMulti bit in the ioFlags field (clearing all other flags bits to 0)
  20026. and use the following parameter block:
  20027.  
  20028. Parameter block
  20029.   -->    12    ioCompletion  pointer
  20030.   <--    16    ioResult      word
  20031.   -->    18    ioNamePtr     pointer
  20032.   <--    22    ioRefNum      word
  20033.   -->    27    ioPermssn     byte
  20034.  
  20035.   -->    28    ioMix         pointer
  20036.   -->    32    ioFlags       word
  20037.   -->    34    ioSEBlkPtr    pointer
  20038.  
  20039. Here the new parameter ioSEBlkPtr is a pointer to an external parameter block
  20040. (described in the Slot Manager chapter) that is customized for the devices installed
  20041. in the slot.  The pointer value is passed to the driver.
  20042.  
  20043. _______________________________________________________________________________
  20044.  
  20045.  
  20046. æKY Slot…Device…Interrupts
  20047. æC »SLOT DEVICE INTERRUPTS                                      DeviceManager
  20048. _______________________________________________________________________________
  20049.  
  20050. Slot interrupts enter the system by way of the Macintosh II VIA2 chip, which contains
  20051. an 8-bit register that has a bit for each slot. This means that there is effectively
  20052. one interrupt line per card.  You can tell almost instantly which card requested the
  20053. interrupt, but not which device on the card.  To locate the interrupt to a device,
  20054. the Slot Manager provides the polling procedure described below.
  20055.  
  20056. The Device Manager maintains an interrupt queue for each slot.  The queue elements
  20057. are ordered by priority and contain pointers to polling routines.  Upon receipt of a
  20058. slot interrupt the Device Manager goes through the slot’s interrupt queue, calling
  20059. each polling routine, until it gets an indication that the interrupt has been satisfied.
  20060.  If no such indication occurs, a system error dialog is displayed.
  20061.  
  20062. The format for a slot interrupt queue element is the following:
  20063.  
  20064.   SQLink    EQU    0    ;link to next element (pointer)
  20065.   SQType    EQU    4    ;queue type ID for validity (word)
  20066.   SQPrio    EQU    6    ;priority (low byte of word)
  20067.   SQAddr    EQU    8    ;interrupt service routine (pointer)
  20068.   SQParm    EQU    12   ;optional A1 parameter (long)
  20069.  
  20070. The SQLink field points to the next queue entry; it is maintained by the system.  The
  20071. SQType field identifies the structure as an element of a slot interrupt queue.  It
  20072. should be set to SIQType.  The SQPrio field is an unsigned byte that determines the
  20073. order in which slots are polled and routines are called.  Higher value routines are
  20074. called sooner. Priority values 200–255 are reserved for Apple devices.  The SQAddr
  20075. field points to the interrupt polling routine.
  20076.  
  20077. •••Refer to Technical Notes #221 & #257:•••
  20078.  
  20079. The SQParm field is a value which is loaded into A1 before calling an interrupt
  20080. service routine.  This could be a handle to the driver’s DCE, for example.
  20081.  
  20082. _______________________________________________________________________________
  20083.  
  20084.  
  20085. æKY New…Routines
  20086. æC »NEW ROUTINES                                                DeviceManager
  20087. _______________________________________________________________________________
  20088.  
  20089. The Device Manager provides two new routines to implement the interrupt queue process
  20090. just described: SIntInstall and SIntRemove. They are described below.
  20091.  
  20092. FUNCTION SIntInstall(sIntQElemPtr: SQElemPtr; theSlot: INTEGER) : OsErr;
  20093.  
  20094. Trap macro  _SIntInstall
  20095. On entry    D0:  slot number (word)
  20096.             A0:  address of slot queue element
  20097. On exit     D0:  error code
  20098.  
  20099. SIntInstall adds a new element (pointed to by sIntQElemPtr) to the interrupt queue
  20100. for the slot whose number is given in theSlot.  As explained in the Slot Manager
  20101. chapter, slots are numbered from 9 to $E.
  20102.  
  20103. Assembly-language note:  From assembly language, this routine has the
  20104.                          following calling sequence (assuming A0 points
  20105.                          to a slot queue element):
  20106.  
  20107.                            LEA          PollRoutine,A1     ;get routine address
  20108.                            MOVE.L       A1,SQAddr(A0)      ;set address
  20109.                            MOVE.W       Prio,SQPrio(A0)    ;set priority
  20110.                            MOVE.L       A1Parm,SQParm(A0)  ;save A1 parameter
  20111.                            MOVE.W       Slot,D0            ;set slot number
  20112.                            _SIntInstall                    ;do installation
  20113.  
  20114.                          This code causes the routine at label PollRoutine to
  20115.                          be called as a result of an interrupt from the
  20116.                          specified slot (9..$E).   The Device Manager will
  20117.                          poll the slot which has the highest priority first if
  20118.                          two or more slots request an interrupt simultaneously.
  20119.  
  20120. FUNCTION SIntRemove(sIntQElemPtr: SQElemPtr; theSlot: INTEGER) : OsErr;
  20121.  
  20122. Trap macro  _SIntRemove
  20123. On entry    D0:  slot number (word)
  20124.             A0:  address of slot queue element
  20125. On exit     D0:  error code
  20126.  
  20127. SIntRemove removes an element (pointed to by sIntQElemPtr) from the interrupt queue
  20128. for the slot whose number is given in theSlot.  As explained in the Slot Manager
  20129. chapter, slots are numbered from 9 to $E.
  20130.  
  20131. Assembly-language note:  From assembly language, this routine has the
  20132.                          following calling sequence (assuming A0 points
  20133.                          to a slot queue element):
  20134.  
  20135.                            LEA         MySQEl,A0    ;pointer to queue element
  20136.                            _SIntRemove              ;remove it
  20137.  
  20138.                          This routine lets you remove an interrupt handler
  20139.                          from the system without causing a crash.
  20140.  
  20141. Your driver polling routine will be called with the following assembly-language
  20142. code:
  20143.  
  20144.   MOVE.L    A1Parm,A1      ;load A1 Parameter
  20145.   JSR       PollRoutine    ;call polling routine
  20146.  
  20147. Your polling routine should preserve the contents of all registers except A1 and D0. 
  20148. It should return to the Device Manager with an RTS instruction. D0 should be set to
  20149. zero to indicate that the polling routine did not service the interrupt, or nonzero
  20150. to indicate the interrupt has been serviced.  The polling routine should not set the
  20151. processor priority below 2, and should return with the processor priority equal to 2.
  20152.  The Device Manager resets the VIA2 int flag and executes an RTE to the interrrupted
  20153. task when a polling routine indicates that the interrupt is satisfied; otherwise, it
  20154. calls the next lower-priority polling routine for that slot.  If none exists, a
  20155. system error results.
  20156.  
  20157. _______________________________________________________________________________
  20158.  
  20159.  
  20160. æKY Summary…of…the…Device…Manager
  20161. æC »SUMMARY OF THE DEVICE MANAGER                               DeviceManager
  20162. _______________________________________________________________________________
  20163.  
  20164. Constants
  20165.  
  20166. CONST
  20167.  
  20168.   { Values for requesting read/write access }
  20169.  
  20170.   fsCurPerm    = 0;    {whatever is currently allowed}
  20171.   fsRdPerm     = 1;    {request to read only}
  20172.   fsWrPerm     = 2;    {request to write only}
  20173.   fsRdWrPerm   = 3;    {request to read and write}
  20174.  
  20175.   { Positioning modes }
  20176.  
  20177.   fsAtMark     = 0;    {at current position}
  20178.   fsFromStart  = 1;    {offset relative to beginning of medium}
  20179.   fsFromMark   = 3;    {offset relative to current position}
  20180.   rdVerify     = 64;   {add to above for read-verify}
  20181.  
  20182.   [Volume IV additions]
  20183.  
  20184.   {Chooser message values}
  20185.  
  20186.   newSelMsg    = 12;   {new user selections have been made}
  20187.   fillListMsg  = 13;   {fill the list with choices to be made}
  20188.   getSelMsg    = 14;   {mark one or more choices as selected}
  20189.   selectMsg    = 15;   {a choice has actually been made}
  20190.   deselectMsg  = 16;   {a choice has been cancelled}
  20191.   terminateMsg = 17;   {lets device package clean up}
  20192.   buttonMsg    = 19;   {tells driver a button has been selected}
  20193.  
  20194.   {caller values}
  20195.  
  20196.   chooserID    = 1;    {caller value for the Chooser}
  20197.  
  20198. _______________________________________________________________________________
  20199.  
  20200. Data Types
  20201.  
  20202. TYPE
  20203.   ParamBlkType  = (ioParam,fileParam,volumeParam,cntrlParam);
  20204.  
  20205.   ParamBlockRec = RECORD
  20206.                     qLink:         QElemPtr;  {next queue entry}
  20207.                     qType:         INTEGER;   {queue type}
  20208.                     ioTrap:        INTEGER;   {routine trap}
  20209.                     ioCmdAddr:     Ptr;       {routine address}
  20210.                     ioCompletion:  ProcPtr;   {completion routine}
  20211.                     ioResult:      OSErr;     {result code}
  20212.                     ioNamePtr:     StringPtr; {driver name}
  20213.                     ioVRefNum:     INTEGER;   {volume reference or }
  20214.                                               { drive number}
  20215.                  CASE ParamBlkType OF
  20216.                   ioParam:
  20217.                    (ioRefNum:     INTEGER;     {driver reference number}
  20218.                     ioVersNum:    SignedByte;  {not used}
  20219.                     ioPermssn:    SignedByte;  {read/write permission}
  20220.                     ioMisc:       Ptr;         {not used}
  20221.                     ioBuffer:     Ptr;         {pointer to data buffer}
  20222.                     ioReqCount:   LONGINT;     {requested number of bytes}
  20223.                     ioActCount:   LONGINT;     {actual number of bytes}
  20224.                     ioPosMode:    INTEGER;     {positioning mode}
  20225.                     ioPosOffset:  LONGINT);    {positioning offset}
  20226.                   fileParam:
  20227.                    . . . {used by the File Manager}
  20228.                   volumeParam:
  20229.                    . . . {used by the File Manager}
  20230.                   cntrlParam:
  20231.                    (ioCRefNum:    INTEGER;     {driver reference number}
  20232.                     csCode:       INTEGER;     {type of Control or Status call}
  20233.                     csParam:      ARRAY[0..10] OF INTEGER); {control or status }
  20234.                                                             { information}
  20235.                 END;
  20236.  
  20237.   DCtlHandle = ^DCtlPtr;
  20238.   DCtlPtr    = ^DCtlEntry;
  20239.   DCtlEntry = RECORD
  20240.                 dCtlDriver:    Ptr;        {pointer to ROM driver or }
  20241.                                            { handle to RAM driver}
  20242.                 dCtlFlags:     INTEGER;    {flags}
  20243.                 dCtlQHdr:      QHdr;       {driver I/O queue header}
  20244.                 dCtlPosition:  LONGINT;    {byte position used by Read }
  20245.                                            { and Write calls}
  20246.                 dCtlStorage:   Handle;     {handle to RAM driver's }
  20247.                                            { private storage}
  20248.                 dCtlRefNum:    INTEGER;    {driver reference number}
  20249.                 dCtlCurTicks:  LONGINT;    {used internally}
  20250.                 dCtlWindow:    WindowPtr;  {pointer to driver's window}
  20251.                 dCtlDelay:     INTEGER;    {number of ticks between }
  20252.                                            { periodic actions}
  20253.                 dCtlEMask:     INTEGER;    {desk accessory event mask}
  20254.                 dCtlMenu:      INTEGER     {menu ID of menu associated
  20255.                                            { with driver}
  20256.               END;
  20257.  
  20258. _______________________________________________________________________________
  20259.  
  20260. High-Level Routines  [Not in ROM]
  20261.  
  20262. FUNCTION OpenDriver  (name:  Str255; VAR refNum:  INTEGER) :  OSErr;
  20263. FUNCTION CloseDriver (refNum:  INTEGER) :  OSErr;
  20264. FUNCTION FSRead      (refNum:  INTEGER; VAR count:  LONGINT;
  20265.                       buffPtr:  Ptr) :  OSErr;
  20266. FUNCTION FSWrite     (refNum:  INTEGER; VAR count:  LONGINT;
  20267.                       buffPtr:  Ptr) :  OSErr;
  20268. FUNCTION Control     (refNum:  INTEGER; csCode:  INTEGER;
  20269.                       csParamPtr:  Ptr) :  OSErr;
  20270. FUNCTION Status      (refNum:  INTEGER; csCode:  INTEGER;
  20271.                       csParamPtr:  Ptr) :  OSErr;
  20272. FUNCTION KillIO      (refNum:  INTEGER) :  OSErr;
  20273.  
  20274. [Volume IV addition]
  20275.  
  20276. FUNCTION Device      (message,caller:  INTEGER; objName,zoneName:  StringPtr;
  20277.                       p1,p2:  LONGINT) :  OSErr;
  20278.  
  20279. [Volume V additions]
  20280.  
  20281. FUNCTION OpenSlot    (paramBlock: paramBlkPtr; aSync: BOOLEAN) : OsErr;
  20282. FUNCTION SIntInstall (sIntQElemPtr: SQElemPtr; theSlot: INTEGER ) : OsErr;
  20283. FUNCTION SIntRemove  (sIntQElemPtr: SQElemPtr; theSlot: INTEGER) : OsErr;
  20284.  
  20285. _______________________________________________________________________________
  20286.  
  20287. Low-Level Routines
  20288.  
  20289. FUNCTION PBOpen (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20290.   -->    12    ioCompletion  pointer
  20291.   <--    16    ioResult      word
  20292.   -->    18    ioNamePtr     pointer
  20293.   <--    24    ioRefNum      word
  20294.   -->    27    ioPermssn     byte
  20295.  
  20296. FUNCTION PBClose (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20297.   -->    12    ioCompletion  pointer
  20298.   <--    16    ioResult      word
  20299.   -->    24    ioRefNum      word
  20300.  
  20301. FUNCTION PBRead (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20302.   -->    12    ioCompletion  pointer
  20303.   <--    16    ioResult      word
  20304.   -->    22    ioVRefNum     word
  20305.   -->    24    ioRefNum      word
  20306.   -->    32    ioBuffer      pointer
  20307.   -->    36    ioReqCount    long word
  20308.   <--    40    ioActCount    long word
  20309.   -->    44    ioPosMode     word
  20310.   <->    46    ioPosOffset   long word
  20311.  
  20312. FUNCTION PBWrite (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20313.   -->    12    ioCompletion  pointer
  20314.   <--    16    ioResult      word
  20315.   -->    22    ioVRefNum     word
  20316.   -->    24    ioRefNum      word
  20317.   -->    32    ioBuffer      pointer
  20318.   -->    36    ioReqCount    long word
  20319.   <--    40    ioActCount    long word
  20320.   -->    44    ioPosMode     word
  20321.   <->    46    ioPosOffset   long word
  20322.  
  20323. FUNCTION PBControl (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20324.   -->    12    ioCompletion  pointer
  20325.   <--    16    ioResult      word
  20326.   -->    22    ioVRefNum     word
  20327.   -->    24    ioRefNum      word
  20328.   -->    26    csCode        word
  20329.   -->    28    csParam       record
  20330.  
  20331. FUNCTION PBStatus (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20332.   -->    12    ioCompletion  pointer
  20333.   <--    16    ioResult      word
  20334.   -->    22    ioVRefNum     word
  20335.   -->    24    ioRefNum      word
  20336.   -->    26    csCode        word
  20337.   <--    28    csParam       record
  20338.  
  20339. FUNCTION PBKillIO (paramBlock:  ParmBlkPtr; async:  BOOLEAN) :  OSErr;
  20340.   -->    12    ioCompletion  pointer
  20341.   <--    16    ioResult      word
  20342.   -->    24    ioRefNum      word
  20343.  
  20344. _______________________________________________________________________________
  20345.  
  20346. Accessing a Driver’s Device Control Entry
  20347.  
  20348. FUNCTION GetDCtlEntry (refNum:  INTEGER) :  DCtlHandle;  [Not in ROM]
  20349.  
  20350. _______________________________________________________________________________
  20351.  
  20352. Result Codes
  20353.  
  20354. Name        Value    Meaning
  20355.  
  20356. abortErr      –27    I/O request aborted by KillIO
  20357. badUnitErr    –21    Driver reference number doesn’t match unit table
  20358. controlErr    –17    Driver can’t respond to this Control call
  20359. dInstErr      –26    Couldn’t find driver in resource file
  20360. dRemovErr     –25    Attempt to remove an open driver
  20361. noErr           0    No error
  20362. notOpenErr    –28    Driver isn’t open
  20363. openErr       –23    Requested read/write permission doesn’t match
  20364.                      driver’s open permission
  20365. readErr       –19    Driver can’t respond to Read calls
  20366. statusErr     –18    Driver can’t respond to this Status call
  20367. unitEmptyErr  –22    Driver reference number specifies NIL handle in unit table
  20368. writErr       –20    Driver can’t respond to Write calls
  20369.  
  20370. _______________________________________________________________________________
  20371.  
  20372. Assembly-Language Information
  20373.  
  20374. Constants
  20375.  
  20376. ; Flags in trap words
  20377.  
  20378. asnycTrpBit    .EQU    10   ;set for an asynchronous call
  20379. noQueueBit     .EQU    9    ;set for immediate execution
  20380.  
  20381. ; Values for requesting read/write access
  20382.  
  20383. fsCurPerm      .EQU    0    ;whatever is currently allowed
  20384. fsRdPerm       .EQU    1    ;request to read only
  20385. fsWrPerm       .EQU    2    ;request to write only
  20386. fsRdWrPerm     .EQU    3    ;request to read and write
  20387.  
  20388. ; Positioning modes
  20389.  
  20390. fsAtMark       .EQU    0    ;at current position
  20391. fsFromStart    .EQU    1    ;offset relative to beginning of medium
  20392. fsFromMark     .EQU    3    ;offset relative to current position
  20393. rdVerify       .EQU   64    ;add to above for read-verify
  20394.  
  20395. ; Driver flags
  20396.  
  20397. dReadEnable    .EQU    0    ;set if driver can respond to Read calls
  20398. dWritEnable    .EQU    1    ;set if driver can respond to Write calls
  20399. dCtlEnable     .EQU    2    ;set if driver can respond to Control calls
  20400. dStatEnable    .EQU    3    ;set if driver can respond to Status calls
  20401. dNeedGoodBye   .EQU    4    ;set if driver needs to be called before the
  20402.                             ; application heap is reinitialized
  20403. dNeedTime      .EQU    5    ;set if driver needs time for performing a
  20404.                             ; periodic action
  20405. dNeedLock      .EQU    6    ;set if driver will be locked in memory as
  20406.                             ; soon as it's opened (always set for ROM drivers)
  20407.  
  20408. ; Device control entry flags
  20409.  
  20410. dOpened        .EQU    5    ;set if driver is open
  20411. dRAMBased      .EQU    6    ;set if driver is RAM-based
  20412. drvrActive     .EQU    7    ;set if driver is currently executing
  20413.  
  20414. ; csCode values for driver control routine
  20415.  
  20416. accRun         .EQU    65   ;take the periodic action, if any, for this driver
  20417. goodBye        .EQU    –1   ;heap will be reinitialized, clean up if necessary
  20418. killCode       .EQU     1   ;handle the KillIO call
  20419.  
  20420. ; Low-order byte of Device Manager traps
  20421.  
  20422. aRdCmd         .EQU    2    ;Read call (trap $A002)
  20423. aWrCmd         .EQU    3    ;Write call (trap $A003)
  20424.  
  20425. ; Offsets from SCC base addresses
  20426.  
  20427. aData          .EQU    6    ;channel A data in or out
  20428. aCtl           .EQU    2    ;channel A control
  20429. bData          .EQU    4    ;channel B data in or out
  20430. bCtl           .EQU    0    ;channel B control
  20431.  
  20432. [Volume IV additions]
  20433.  
  20434. ; Chooser message values
  20435.  
  20436. newSel         .EQU   12    ;new user selections have been made
  20437. fillList       .EQU   13    ;fill the list with choices to be made
  20438. getSel         .EQU   14    ;mark one or more choices as selected
  20439. select         .EQU   15    ;a choice has actually been made
  20440. deselect       .EQU   16    ;a choice has been cancelled
  20441. terminate      .EQU   17    ;lets device package clean up
  20442. button         .EQU   19    ;tells driver a button has been selected
  20443.  
  20444. ; Caller values
  20445.  
  20446. chooserID      .EQU    1    ;caller value for the Chooser
  20447.  
  20448. [Volume V additions]
  20449.  
  20450. ; Slot Queue Element
  20451.  
  20452. SQLink          EQU    0    ;link to next element (pointer)
  20453. SQType          EQU    4    ;queue type ID for validity (word)
  20454. SQPrio          EQU    6    ;priority (low byte of word)
  20455. SQAddr          EQU    8    ;interrupt service routine (pointer)
  20456. SQParm          EQU   12    ;optional A1 parameter (long)
  20457.  
  20458. SIQType         EQU    6    ;slot interrupt queue element type
  20459.  
  20460. Standard Parameter Block Data Structure
  20461.  
  20462. qLink         Pointer to next queue entry
  20463. qType         Queue type (word)
  20464. ioTrap        Routine trap (word)
  20465. ioCmdAddr     Routine address
  20466. ioCompletion  Address of completion routine
  20467. ioResult      Result code (word)
  20468. ioVNPtr       Pointer to driver name (preceded by length byte)
  20469. ioVRefNum     Volume reference number (word)
  20470. ioDrvNum      Drive number (word)
  20471.  
  20472. Control and Status Parameter Block Data Structure
  20473.  
  20474. ioRefNum      Driver reference number (word)
  20475. csCode        Type of Control or Status call (word)
  20476. csParam       Parameters for Control or Status call (22 bytes)
  20477.  
  20478. I/O Parameter Block Data Structure
  20479.  
  20480. ioRefNum      Driver reference number (word)
  20481. ioPermssn     Open permission (byte)
  20482. ioBuffer      Pointer to data buffer
  20483. ioReqCount    Requested number of bytes (long)
  20484. ioActCount    Actual number of bytes (long)
  20485. ioPosMode     Positioning mode (word)
  20486. ioPosOffset   Positioning offset (long)
  20487.  
  20488. Device Driver Data Structure
  20489.  
  20490. drvrFlags     Flags (word)
  20491. drvrDelay     Number of ticks between periodic actions (word)
  20492. drvrEMask     Desk accessory event mask (word)
  20493. drvrMenu      Menu ID of menu associated with driver (word)
  20494. drvrOpen      Offset to open routine (word)
  20495. drvrPrime     Offset to prime routine (word)
  20496. drvrCtl       Offset to control routine (word)
  20497. drvrStatus    Offset to status routine (word)
  20498. drvrClose     Offset to close routine (word)
  20499. drvrName      Driver name (preceded by length byte)
  20500.  
  20501. Device Control Entry Data Structure
  20502.  
  20503. dCtlDriver    Pointer to ROM driver or handle to RAM driver
  20504. dCtlFlags     Flags (word)
  20505. dCtlQueue     Queue flags:  low-order byte is driver’s version number (word)
  20506. dCtlQHead     Pointer to first entry in driver’s I/O queue
  20507. dCtlQTail     Pointer to last entry in driver’s I/O queue
  20508. dCtlPosition  Byte position used by Read and Write calls (long)
  20509. dCtlStorage   Handle to RAM driver’s private storage
  20510. dCtlRefNum    Driver’s reference number (word)
  20511. dCtlWindow    Pointer to driver’s window
  20512. dCtlDelay     Number of ticks between periodic actions (word)
  20513. dCtlEMask     Desk accessory event mask (word)
  20514. dCtlMenu      Menu ID of menu associated with driver (word)
  20515.  
  20516. Structure of Primary Interrupt Vector Table
  20517.  
  20518. autoInt1    Vector to level-1 interrupt handler
  20519. autoInt2    Vector to level-2 interrupt handler
  20520. autoInt3    Vector to level-3 interrupt handler
  20521. autoInt4    Vector to level-4 interrupt handler
  20522. autoInt5    Vector to level-5 interrupt handler
  20523. autoInt6    Vector to level-6 interrupt handler
  20524. autoInt7    Vector to level-7 interrupt handler
  20525.  
  20526. [Volume IV additions]
  20527.  
  20528. Device Package Data Structure
  20529.  
  20530. Byte    Value
  20531.  
  20532.  0      BRA.S to offset $10
  20533.  2      Device ID (word)
  20534.  4      'PACK' (long word)
  20535.  8      $F000 (–4096)
  20536.  A      Version (word)
  20537.  C      Flags (long word)
  20538.  10     Start of driver code
  20539.  
  20540. [Volume V additions]
  20541.  
  20542. Device Control Entry Data Structure
  20543.  
  20544. dCtlDriver    Pointer to ROM driver or handle to RAM driver
  20545. dCtlFlags     Flags (word)
  20546. dCtlQueue     Queue flags:  low-order byte is driver’s version number (word)
  20547. dCtlQHead     Pointer to first entry in driver’s I/O queue
  20548. dCtlQTail     Pointer to last entry in driver’s I/O queue
  20549. dCtlPosition  Byte position used by Read and Write calls (long)
  20550. dCtlStorage   Handle to RAM driver’s private storage
  20551. dCtlRefNum    Driver’s reference number (word)
  20552. dCtlWindow    Pointer to driver’s window
  20553. dCtlDelay     Number of ticks between periodic actions (word)
  20554. dCtlEMask     Desk accessory event mask (word)
  20555. dCtlMenu      Menu ID of menu associated with driver (word)
  20556. dCtlSlot      Slot number (byte)
  20557. dCtlSlotID    Resource directory ID number for sResource (byte)
  20558. dCtlDevBase   Device base address (pointer)
  20559. reserved      Longint reserved for future use (should be 0)
  20560. dCtlExtDev    External device ID (byte)
  20561.  
  20562. OpenSlot Parameter Blocks
  20563.  
  20564. If fMulti bit in ioFlags = 0:
  20565.   -->    12    ioCompletion  pointer
  20566.   <--    16    ioResult      word
  20567.   -->    18    ioNamePtr     pointer
  20568.   <--    22    ioRefNum      word
  20569.   -->    27    ioPermssn     byte
  20570.  
  20571.   -->    28    ioMix         pointer
  20572.   -->    32    ioFlags       word
  20573.   -->    34    ioSlot        byte
  20574.   -->    35    ioId          byte
  20575.  
  20576. If fMulti bit in ioFlags = 1:
  20577.   -->    12    ioCompletion  pointer
  20578.   <--    16    ioResult      word
  20579.   -->    18    ioNamePtr     pointer
  20580.   <--    22    ioRefNum      word
  20581.   -->    26    ioPermssn     byte
  20582.  
  20583.   -->    28    ioMix         pointer
  20584.   -->    32    ioFlags       word
  20585.   -->    34    ioSEBlkPtr    pointer
  20586.  
  20587. Macro Names
  20588.  
  20589. Pascal name    Macro name
  20590.  
  20591. PBRead         _Read
  20592. PBWrite        _Write
  20593. PBControl      _Control
  20594. PBStatus       _Status
  20595. PBKillIO       _KillIO
  20596.  
  20597. Volume V additions
  20598.  
  20599. sIntInstall    _sIntInstall
  20600. sIntRemove     _sIntRemove
  20601.  
  20602. _______________________________________________________________________________
  20603.  
  20604. Routines for Writing Drivers
  20605.  
  20606. Routine   Jump vector    On entry              On exit
  20607.  
  20608. Fetch     JFetch         A1:  ptr to device    D0:  character fetched; bit 15=1
  20609.                               control entry         if last character in buffer
  20610. Stash     JStash         A1:  ptr to device    D0:  bit 15=1 if last character
  20611.                               control entry         requested
  20612.                          D0:  character to stash
  20613. IODone    JIODone        A1:  ptr to device
  20614.                               control entry
  20615.                          D0:  result code (word)
  20616.  
  20617. Variables
  20618.  
  20619. UTableBase    Base address of unit table
  20620. JFetch        Jump vector for Fetch function
  20621. JStash        Jump vector for Stash function
  20622. JIODone       Jump vector for IODone function
  20623. Lvl1DT        Level-1 secondary interrupt vector table (32 bytes)
  20624. Lvl2DT        Level-2 secondary interrupt vector table (32 bytes)
  20625. VIA           VIA base address
  20626. ExtStsDT      External/status interrupt vector table (16 bytes)
  20627. SCCWr        SCC write base address
  20628. SCCRd        SCC read base address
  20629.  
  20630. Further Reference:
  20631. _______________________________________________________________________________
  20632. Resource Manager
  20633. Desk Manager
  20634. File Manager
  20635. OS Utilities
  20636. Start Manager
  20637. Slot Manager
  20638. List Manager Package
  20639. Disk Driver
  20640. Serial Drivers
  20641. Technical Note #36, Drive Queue Elements
  20642. Technical Note #56, Break/CTS Device Driver Event Structure
  20643. Technical Note #71, Finding Drivers in the Unit Table
  20644. Technical Note #108, AddDrive, DrvrInstall and DrvrRemove
  20645. Technical Note #187, Don’t Look at ioPosOffset
  20646. Technical Note #197, Chooser Enhancements
  20647. Technical Note #208, Setting and Restoring A5
  20648. Technical Note #221, NuBus Interrupt Latency
  20649. Technical Note #250, AppleTalk Phase 2 on the Macintosh
  20650. Technical Note #257, Slot Interrupt Prio-Technics
  20651. Q & A Stack
  20652. “Macintosh Family Hardware Reference”
  20653. “Designing Cards and Drivers for the Macintosh II and Macintosh SE”
  20654.  
  20655. æKY DialogManager
  20656. æC 
  20657. THE DIALOG MANAGER                                     
  20658. _______________________________________________________________________________
  20659.  
  20660. About…The…DialogManager…Chapter
  20661. About…the…Dialog…Manager
  20662. Dialog…and…Alert…Windows
  20663. Dialogs…Alerts…and…Resources
  20664. Color…Alert…and…Dialog…Resources
  20665. Item…Lists…in…Memory
  20666. Color…Dialog…Item…Lists
  20667. Using…Color…Dialogs…and…Alerts
  20668. Dialog…Records
  20669. Alerts
  20670. Using…the…Dialog…Manager
  20671. Dialog…Manager…Routines
  20672. Modifying…Templates…in…Memory
  20673. Formats…of…Resources…for…Dialogs…and…Alerts
  20674. Summary…of…the…Dialog…Manager
  20675. _______________________________________________________________________________
  20676.  
  20677.  
  20678.  
  20679. æKY About…The…DialogManager…Chapter
  20680. æC »ABOUT THIS CHAPTER                                          DialogManager
  20681. _______________________________________________________________________________
  20682.  
  20683. This chapter describes the Dialog Manager, the part of the Toolbox that allows you to
  20684. implement dialog boxes and the alert mechanism, two means of communication between
  20685. the application and the end user.
  20686.  
  20687. This chapter also describes the enhancements to the Dialog Manager for the Macintosh
  20688. II. A new Dialog Manager routine now provides color dialog and item support.  The new
  20689. resource types 'dctb', 'actb', and 'ictb', which are auxiliary data structures to
  20690. 'DITL', 'ALRT', and 'DLOG', allow color dialog boxes and alert boxes to be stored as
  20691. resources. If the 'ALRT', 'DLOG', or
  20692. 'DITL' resources are missing, the Dialog Manager will gracefully return from the
  20693. Alert, NoteAlert, CautionAlert, StopAlert, and GetNewDialog calls.
  20694.  
  20695. You should already be familiar with:
  20696.  
  20697.   •  resources, as discussed in the Resource Manager chapter
  20698.   •  the basic concepts and structures behind QuickDraw, particularly
  20699.      rectangles, grafPorts, and pictures
  20700.   •  the Toolbox Event Manager, the Window Manager, and the Control Manager
  20701.   •  TextEdit, to understand editing text in dialog boxes
  20702.  
  20703. _______________________________________________________________________________
  20704.  
  20705.  
  20706. æKY About…the…Dialog…Manager
  20707. æC »ABOUT THE DIALOG MANAGER                                    DialogManager
  20708. _______________________________________________________________________________
  20709.  
  20710. The Dialog Manager is a tool for handling dialogs and alerts in a way that’s consistent
  20711. with the Macintosh User Interface Guidelines.
  20712. A dialog box appears on the screen when a Macintosh application needs more information
  20713. to carry out a command. As shown in Figure 1, it typically resembles a form on which
  20714. the user checks boxes and fills in blanks.
  20715.  
  20716. •••Refer to Figure 1.•••
  20717.  
  20718. Figure 1–A Typical Dialog Box
  20719.  
  20720. By convention, a dialog box comes up slightly below the menu bar, is somewhat narrower
  20721. than the screen, and is centered between the left and right edges of the screen. It
  20722. may contain any or all of the following:
  20723.  
  20724.   •  informative or instructional text
  20725.   •  rectangles in which text may be entered (initially blank or
  20726.      containing default text that can be edited)
  20727.   •  controls of any kind
  20728.   •  graphics (icons or QuickDraw pictures)
  20729.   •  anything else, as defined by the application
  20730.  
  20731. The user provides the necessary information in the dialog box, such as by entering
  20732. text or clicking a check box. There’s usually a button labeled “OK” to tell the
  20733. application to accept the information provided and perform the command, and a button
  20734. labeled “Cancel” to cancel the command as though it had never been given (retracting
  20735. all actions since its invocation). Some dialog boxes may use a more descriptive word
  20736. than “OK”; for simplicity, this chapter will still refer to the button as the “OK
  20737. button”. There may even be more than one button that will perform the command, each
  20738. in a different way.
  20739.  
  20740. Most dialog boxes require the user to respond before doing anything else. Clicking a
  20741. button to perform or cancel the command makes the box go away; clicking outside the
  20742. dialog box only causes a beep from the Macintosh’s speaker. This type is called a
  20743. modal dialog box because it puts the user in the state or “mode” of being able to
  20744. work only inside the dialog box. A modal dialog box usually has the same general
  20745. appearance as shown in Figure 1 above. One of the buttons in the dialog box may be
  20746. outlined boldly. Pressing the Return key or the Enter key has the same effect as
  20747. clicking the outlined button or, if none, the OK button; the particular button whose
  20748. effect occurs is called the dialog’s default button and is the preferred (“safest”)
  20749. button to use in the current situation. If there’s no boldly outlined or OK button,
  20750. pressing Return or Enter will by convention have no effect.
  20751.  
  20752. Other dialog boxes do not require the user to respond before doing anything else;
  20753. these are called modeless dialog boxes (see Figure 2). The user can, for example, do
  20754. work in document windows on the desktop before clicking a button in the dialog box,
  20755. and modeless dialog boxes can be set up to respond to the standard editing commands
  20756. in the Edit menu. Clicking a button in a modeless dialog box will not make the box go
  20757. away:  The box will stay around so that the user can perform the command again. A
  20758. Cancel button, if present, will simply stop the action currently being performed by
  20759. the command; this would be useful for long printing or searching operations, for
  20760. example.
  20761.  
  20762. •••Refer to Figure 2.•••
  20763.  
  20764. Figure 2–A Modeless Dialog Box
  20765.  
  20766. As shown in Figure 2, a modeless dialog box looks like a document window. It can be
  20767. moved, made inactive and active again, or closed like any document window. When
  20768. you’re done with the command and want the box to go away, you can click its close box
  20769. or choose Close from the File menu when it’s the active window.
  20770.  
  20771. Dialog boxes may in fact require no response at all. For example, while an application
  20772. is performing a time-consuming process, it can display a dialog box that contains
  20773. only a message telling what it’s doing; then, when the process is complete, it can
  20774. simply remove the dialog box.
  20775.  
  20776. The alert mechanism provides applications with a means of reporting errors or giving
  20777. warnings. An alert box is similar to a modal dialog box, but it appears only when
  20778. something has gone wrong or must be brought to the user’s attention. Its conventional
  20779. placement is slightly farther below the menu bar than a dialog box. To assist the
  20780. user who isn’t sure how to proceed when an alert box appears, the preferred button to
  20781. use in the current situation is outlined boldly so it stands out from the other
  20782. buttons in the alert box (see Figure 3). The outlined button is also the alert’s
  20783. default button; if the user presses the Return key or the Enter key, the effect is
  20784. the same as clicking this button.
  20785.  
  20786. •••Refer to Figure 3.•••
  20787.  
  20788. Figure 3–A Typical Alert Box
  20789.  
  20790. There are three standard kinds of alerts—Stop, Note, and Caution—each indicated by a
  20791. particular icon in the top left corner of the alert box. Figure 3 illustrates a
  20792. Caution alert. The icons identifying Stop and Note alerts are similar; instead of a
  20793. question mark, they show an exclamation point and an asterisk, respectively. Other
  20794. alerts can have anything in the the top left corner, including blank space if desired.
  20795.  
  20796. The alert mechanism also provides another type of signal:  Sound from the Macintosh’s
  20797. speaker. The application can base its response on the number of consecutive times an
  20798. alert occurs; the first time, it might simply beep, and thereafter it may present an
  20799. alert box. The sound isn’t limited to a single beep but may be any sequence of tones,
  20800. and may occur either alone or along with an alert box. As an error is repeated, there
  20801. can also be a change in which button is the default button (perhaps from OK to Cancel).
  20802. You can specify different responses for up to four occurrences of the same alert.
  20803.  
  20804. With Dialog Manager routines, you can create dialog boxes or invoke alerts. The
  20805. Dialog Manager gets most of the descriptive information about the dialogs and alerts
  20806. from resources in a resource file. The Dialog Manager calls the Resource Manager to
  20807. read what it needs from the resource file into memory as necessary. In some cases you
  20808. can modify the information after it’s been read into memory.
  20809.  
  20810. Four routines—HideDItem, ShowDItem, FindDItem, and UpdtDialog—have been added to the
  20811. Dialog Manager.
  20812.  
  20813. Advanced programmers:  The standard filterProc function called by
  20814.                        ModalDialog now returns 1 in itemHit and a
  20815.                        function result of TRUE only if the first item
  20816.                        is enabled.
  20817.  
  20818. Automatic scrolling is supported in editText items.
  20819.  
  20820. _______________________________________________________________________________
  20821.  
  20822.  
  20823. æKY Dialog…and…Alert…Windows
  20824. æC »DIALOG AND ALERT WINDOWS                                    DialogManager
  20825. _______________________________________________________________________________
  20826.  
  20827. A dialog box appears in a dialog window. When you call a Dialog Manager routine to
  20828. create a dialog, you supply the same information as when you create a window with a
  20829. Window Manager routine. For example, you supply the window definition ID, which
  20830. determines how the window looks and behaves, and a rectangle that becomes the portRect
  20831. of the window’s grafPort. You specify the window’s plane (which, by convention,
  20832. should initially be the frontmost) and whether the window is visible or invisible.
  20833. The dialog window is created as specified.
  20834.  
  20835. You can manipulate a dialog window just like any other window with Window Manager or
  20836. QuickDraw routines, showing it, hiding it, moving it, changing its size or plane, or
  20837. whatever— all, of course, in conformance with the Macintosh User Interface Guidelines.
  20838. The Dialog Manager observes the clipping region of the dialog window’s grafPort, so
  20839. if you want clipping to occur, you can set this region with a QuickDraw routine.
  20840.  
  20841. Similarly, an alert box appears in an alert window. You don’t have the same flexibility
  20842. in defining and manipulating an alert window, however. The Dialog Manager chooses the
  20843. window definition ID, so that all alert windows will have the standard appearance and
  20844. behavior. The size and location of the box are supplied as part of the definition of
  20845. the alert and are not easily changed. You don’t specify the alert window’s plane; it
  20846. always comes up in front of all other windows. Since an alert box requires the user
  20847. to respond before doing anything else, and the response makes the box go away, the
  20848. application doesn’t do any manipulation of the alert window.
  20849.  
  20850.  
  20851. Figure 4 illustrates a document window, dialog window, and alert window, all overlapping
  20852. on the desktop.
  20853.  
  20854. •••Refer to Figure 4.•••
  20855.  
  20856. Figure 4–Dialog and Alert Windows
  20857.  
  20858. _______________________________________________________________________________
  20859.  
  20860.  
  20861. æKY Dialogs…Alerts…and…Resources
  20862. æC »DIALOGS, ALERTS, AND RESOURCES                              DialogManager
  20863. _______________________________________________________________________________
  20864.  
  20865. To create a dialog, the Dialog Manager needs the same information about the dialog
  20866. window as the Window Manager needs when it creates a new window:  The window definition
  20867. ID along with other information specific to this window. The Dialog Manager also
  20868. needs to know what items the dialog box contains. You can store the needed information
  20869. as a resource in a resource file and pass the resource ID to a function that will
  20870. create the dialog. This type of resource, which is called a dialog template, is
  20871. analogous to a window template, and the function, GetNewDialog, is similar to the
  20872. Window Manager function GetNewWindow. The Dialog Manager calls the Resource Manager
  20873. to read the dialog template from the resource file. It then incorporates the information
  20874. in the template into a dialog data structure in memory, called a dialog record.
  20875.  
  20876. Similarly, the data that the Dialog Manager needs to create an alert is stored in an
  20877. alert template in a resource file. The various routines for invoking alerts require
  20878. the resource ID of the alert template as a parameter.
  20879.  
  20880. The information about all the items (text, controls, or graphics) in a dialog or
  20881. alert box is stored in an item list in a resource file. The resource ID of the item
  20882. list is included in the dialog or alert template. The item list in turn contains the
  20883. resource IDs of any icons or QuickDraw pictures in the dialog or alert box, and
  20884. possibly the resource IDs of control templates for controls in the box. After calling
  20885. the Resource Manager to read a dialog or alert template into memory, the Dialog
  20886. Manager calls it again to read in the item list. It then makes a copy of the item
  20887. list and uses that copy; for this reason, item lists should always be purgeable
  20888. resources. Finally, the Dialog Manager calls the Resource Manager to read in any
  20889. individual items as necessary.
  20890.  
  20891. If desired, the application can gain some additional flexibility by calling the
  20892. Resource Manager directly to read templates, item lists, or items from a resource
  20893. file. For example, you can read in a dialog or alert template directly and modify
  20894. some of the information in it before calling the routine to create the dialog or
  20895. alert. Or, as an alternative to using a dialog template, you can read in a dialog’s
  20896. item list directly and then pass a handle to it along with other information to a
  20897. function that will create the dialog (NewDialog, analogous to the Window Manager
  20898. function NewWindow).
  20899.  
  20900. Note:  The use of dialog templates is recommended wherever possible; like
  20901.        window templates, they isolate descriptive information from your
  20902.        application code for ease of modification or translation to other
  20903.        languages.
  20904.  
  20905. _______________________________________________________________________________
  20906.  
  20907.  
  20908. æKY Color…Alert…and…Dialog…Resources
  20909. æC »COLOR ALERT AND DIALOG RESOURCES                            DialogManager
  20910. _______________________________________________________________________________
  20911.  
  20912. You don’t have to call any new routines to create color alert or dialog boxes. Additional
  20913. resources of types 'actb', 'dctb', and 'ictb' complement the existing 'ALRT', 'DLOG',
  20914. and 'DITL' resources, and provide all the information needed to color dialog windows,
  20915. controls, and text.
  20916.  
  20917. To create a dialog or alert box, the Dialog Manager needs the same information about
  20918. the box as the Window Manager needs when it creates a new window. The structure of
  20919. dialog color tables and alert color tables is similar to the window color table
  20920. described in the Window Manager chapter, as shown in
  20921. Figure 5.
  20922.  
  20923. •••Refer to Figure 5.•••
  20924.  
  20925. Figure 5–Color Table for Dialogs and Alerts.
  20926.  
  20927. The calls Alert, CautionAlert, StopAlert, and NoteAlert look for a resource of type
  20928. 'actb' with the same resource ID as the alert.  GetNewDialog looks for a resource of
  20929. type 'dctb' with the same resource ID as the dialog.  These resources contain color
  20930. tables identical to the 'wctb' color tables described in the Window Manager GetNewCWindow
  20931. call.  If an 'actb' or 'dctb' resource is present, then the window created will be a
  20932. cGrafPort, created with a NewCWindow call. If the ctSize field of a 'dctb' or 'actb'
  20933. resource is –1, the default window colors will be used.
  20934.  
  20935. To include a color icon in a dialog box, add a resource of type 'cicn' with the same
  20936. resource ID as an old-style icon. The Dialog Manager will then access the icon with
  20937. the QuickDraw routine GetCIcon.
  20938.  
  20939. To include a version 2 picture in a dialog, create a color table for the dialog to
  20940. cause the dialog to use a cGrafPort. See the Color QuickDraw chapter for more information
  20941. on the use of color pictures.
  20942.  
  20943. To color controls in a dialog, or to change the color, style, font, or size of text
  20944. within a dialog, include an 'ictb' resource as described in the following section.
  20945.  
  20946. Color table resources 'actb' and 'dctb' are treated the same as 'ALRT' resources and
  20947. 'DLOG' resources. The 'ictb' resource is handled just like the
  20948. 'DITL' resource. These resources are preloaded and made nonpurgeable by CouldAlert
  20949. and CouldDialog, and their original purge state is restored by FreeAlert and FreeDialog.
  20950.  
  20951. _______________________________________________________________________________
  20952.  
  20953.  
  20954. æKY Item…Lists…in…Memory
  20955. æC »ITEM LISTS IN MEMORY                                        DialogManager
  20956. _______________________________________________________________________________
  20957.  
  20958. This section discusses the contents of an item list once it’s been read into memory
  20959. from a resource file and the Dialog Manager has set it up as necessary to be able to
  20960. work with it.
  20961.  
  20962. An item list in memory contains the following information for each item:
  20963.  
  20964.   •  The type of item. This includes not only whether the item is a control,
  20965.      text, or whatever, but also whether the Dialog Manager should return to
  20966.      the application when the item is clicked.
  20967.   •  A handle to the item or, for special application-defined items, a
  20968.      pointer to a procedure that draws the item.
  20969.   •  A display rectangle, which determines the location of the item within
  20970.      the dialog or alert box.
  20971.  
  20972. These are discussed below along with item numbers, which identify particular items in
  20973. the item list.
  20974.  
  20975. There’s a Dialog Manager procedure that, given a pointer to a dialog record and an
  20976. item number, sets or returns that item’s type, handle (or procedure pointer), and
  20977. display rectangle.
  20978.  
  20979. _______________________________________________________________________________
  20980.  
  20981. »Item Types
  20982.  
  20983. The item type is specified by a predefined constant or combination of constants, as
  20984. listed below. Figure 6 illustrates some of these item types.
  20985.  
  20986. •••Refer to Figure 6.•••
  20987.  
  20988. Figure 6–Item Types
  20989.  
  20990.   Item type           Meaning
  20991.  
  20992.   ctrlItem+btnCtrl    A standard button control.
  20993.   ctrlItem+chkCtrl    A standard check box control.
  20994.   ctrlItem+radCtrl    A standard radio button control.
  20995.   ctrlItem+resCtrl    A control defined in a control template
  20996.                       in a resource file.
  20997.   statText            Static text; text that cannot be edited.
  20998.   editText            (Dialogs only) Text that can be edited;
  20999.                       the Dialog Manager accepts text typed by
  21000.                       the user and allows editing.
  21001.   iconItem            An icon.
  21002.   picItem             A QuickDraw picture.
  21003.   userItem            (Dialogs only) An application-defined item,
  21004.                       such as a picture whose appearance changes.
  21005.   itemDisable+<any    The item is disabled (the Dialog Manager doesn’t
  21006.   of the above>       report events involving this item).
  21007.  
  21008. The text of an editText item may initially be either default text or empty. Text
  21009. entry and editing is handled in the conventional way, as in TextEdit—in fact, the
  21010. Dialog Manager calls TextEdit to handle it:
  21011.  
  21012.   •  Clicking in the item displays a blinking vertical bar, indicating
  21013.      an insertion point where text may be entered.
  21014.   •  Dragging over text in the item selects that text, and double-clicking
  21015.      selects a word; the selection is highlighted and then replaced by
  21016.      what the user types.
  21017.   •  Clicking or dragging while holding down the Shift key extends or
  21018.      shortens the current selection.
  21019.   •  The Backspace key deletes the current selection or the character
  21020.      preceding the insertion point.
  21021.  
  21022. The Tab key advances to the next editText item in the item list, wrapping around to
  21023. the first if there aren’t any more. In an alert box or a modal dialog box (regardless
  21024. of whether it contains an editText item), the Return key or Enter key has the same
  21025. effect as clicking the default button; for alerts, the default button is identified
  21026. in the alert template, whereas for modal dialogs it’s always the first item in the
  21027. item list.
  21028.  
  21029. If itemDisable is specified for an item, the Dialog Manager doesn’t let the application
  21030. know about events involving that item. For example, you may not have to be informed
  21031. every time the user types a character or clicks in an editText item, but may only
  21032. need to look at the text when the OK button is clicked. In this case, the editText
  21033. item would be disabled. Standard buttons and check boxes should always be enabled, so
  21034. your application will know when they’ve been clicked.
  21035.  
  21036. Warning:  Don’t confuse disabling a control with making one “inactive”
  21037.           with the Control Manager procedure HiliteControl:  When you
  21038.           want a control not to respond at all to being clicked, you
  21039.           make it inactive. An inactive control is highlighted to show
  21040.           that it’s inactive, while disabling a control doesn’t affect
  21041.           its appearance.
  21042.  
  21043. _______________________________________________________________________________
  21044.  
  21045. »Item Handle or Procedure Pointer
  21046.  
  21047. The item list contains the following information for the various types of items:
  21048.  
  21049.   Item type       Contents
  21050.  
  21051.   any ctrlItem    A control handle
  21052.   statText        A handle to the text
  21053.   editText        A handle to the current text
  21054.   iconItem        A handle to the icon
  21055.   picItem         A picture handle
  21056.   userItem        A procedure pointer
  21057.  
  21058. The procedure for a userItem draws the item; for example, if the item is a clock, it
  21059. will draw the clock with the current time displayed. When this procedure is called,
  21060. the current port will have been set by the Dialog Manager to the dialog window’s
  21061. grafPort. The procedure must have two parameters, a window pointer and an item number.
  21062. For example, this is how it would be declared if it were named MyItem:
  21063.  
  21064. PROCEDURE MyItem (theWindow:  WindowPtr; itemNo:  INTEGER);
  21065.  
  21066. TheWindow is a pointer to the dialog window; in case the procedure draws in more than
  21067. one dialog window, this parameter tells it which one to draw in. ItemNo is the item
  21068. number; in case the procedure draws more than one item, this parameter tells it which
  21069. one to draw.
  21070.  
  21071. _______________________________________________________________________________
  21072.  
  21073. »Display Rectangle
  21074.  
  21075. Each item in the item list is displayed within its display rectangle:
  21076.  
  21077.   •  For controls, the display rectangle becomes the control’s
  21078.      enclosing rectangle.
  21079.   •  For an editText item, it becomes TextEdit’s destination rectangle
  21080.      and view rectangle. Word wraparound occurs, and the text is clipped
  21081.      if there’s more than will fit in the rectangle. In addition, the
  21082.      Dialog Manager uses the QuickDraw procedure FrameRect to draw a
  21083.      rectangle three pixels outside the display rectangle.
  21084.   •  StatText items are displayed in exactly the same way as editText
  21085.      items, except that a rectangle isn’t drawn outside the display rectangle.
  21086.   •  Icons and QuickDraw pictures are scaled to fit the display rectangle.
  21087.      For pictures, the Window Manager calls the QuickDraw procedure
  21088.      DrawPicture and passes it the display rectangle.
  21089.   •  If the procedure for a userItem draws outside the item’s display
  21090.      rectangle, the drawing is clipped to the display rectangle.
  21091.  
  21092. Note:  Clicking anywhere within the display rectangle is considered a
  21093.        click in that item. If display rectangles overlap, a click in
  21094.        the overlapping area is considered a click in whichever item
  21095.        comes first in the item list.
  21096.  
  21097. By giving an item a display rectangle that’s off the screen, you can make the item
  21098. invisible. This might be useful, for example, if your application needs to display a
  21099. number of dialog boxes that are similar except that one item is missing or different
  21100. in some of them. You can use a single dialog box in which the item or items that
  21101. aren’t currently relevant are invisible. To remove an item or make one reappear, you
  21102. just change its display rectangle (and call the Window Manager procedure InvalRect to
  21103. accumulate the changed area into the dialog window’s update region). The QuickDraw
  21104. procedure OffsetRect is convenient for moving an item off the screen and then on
  21105. again later. Note the following, however:
  21106.  
  21107.   •  You shouldn’t make an editText item invisible, because it may cause
  21108.      strange things to happen. If one of several editText items is invisible,
  21109.      for example, pressing the Tab key may make the insertion point disappear.
  21110.      However, if you do make this type of item invisible, remember that the
  21111.      changed area includes the rectangle that’s three pixels outside the
  21112.      item’s display rectangle.
  21113.   •  The rectangle for a statText item must always be at least as wide as
  21114.      the first character of the text; a good rule of thumb is to make it
  21115.      at least 20 pixels wide.
  21116.   •  To change text in a statText item, it’s easier to use the Dialog
  21117.      Manager procedure ParamText (as described later in the “Dialog Manager
  21118.      Routines” section).
  21119.  
  21120. _______________________________________________________________________________
  21121.  
  21122. »Item Numbers
  21123.  
  21124. Each item in an item list is identified by an item number, which is simply the index
  21125. of the item in the list (starting from 1). By convention, the first item in an alert’s
  21126. item list should be the OK button (or, if none, then one of the buttons that will
  21127. perform the command) and the second item should be the Cancel button. The Dialog
  21128. Manager provides predefined constants equal to the item numbers for OK and Cancel:
  21129.  
  21130. CONST ok        = 1;
  21131.       cancel    = 2;
  21132.  
  21133. In a modal dialog’s item list, the first item is assumed to be the dialog’s default
  21134. button; if the user presses the Return key or Enter key, the Dialog Manager normally
  21135. returns item number 1, just as when that item is actually clicked. To conform to the
  21136. Macintosh User Interface Guidelines, the application should boldly outline the dialog’s
  21137. default button if it isn’t the OK button. The best way to do this is with a userItem.
  21138. To allow for changes in the default button’s size or location, the userItem should
  21139. identify which button to outline by its item number and then use that number to get
  21140. the button’s display rectangle. The following QuickDraw calls will outline the rectangle
  21141. in the standard way:
  21142.  
  21143.   PenSize(3,3);
  21144.   InsetRect(displayRect,–4,–4);
  21145.   FrameRoundRect(displayRect,16,16)
  21146.  
  21147. Warning:  If the first item in a modal dialog’s item list isn’t an OK
  21148.           button and you don’t boldly outline it, you should set up the
  21149.           dialog to ignore Return and Enter. To learn how to do this,
  21150.           see ModalDialog under “Handling Dialog Events” in the “Dialog
  21151.           Manager Routines” section.
  21152.  
  21153. _______________________________________________________________________________
  21154.  
  21155.  
  21156. æKY Color…Dialog…Item…Lists
  21157. æC »COLOR DIALOG ITEM LISTS                                     DialogManager
  21158. _______________________________________________________________________________
  21159.  
  21160. This section discusses the contents of an item list after it’s been read into memory
  21161. from a resource file. If a resource of type 'ictb' is present with the same resource
  21162. ID as the 'DITL' resource (in addition to the presence of the
  21163. 'dctb' or 'actb' resources), then the statText, editText, and control items in the
  21164. dialog or alert boxes are drawn using the colors and text styles indicated by the
  21165. item color table record contained in the resource.
  21166.  
  21167. Note:  Neither the display device nor the dialog box needs to be in color,
  21168.        but a dialog or alert color table must exist to include an item color
  21169.        table (even if the item color table only describes statText and editText
  21170.        style changes and has no actual color information).
  21171.  
  21172. Figure 7 shows how a dialog color table stores item color table records.
  21173.  
  21174. •••Refer to Figure 7.•••
  21175.  
  21176. Figure 7–Color Table for Dialogs and Alerts.
  21177.  
  21178. The record starts with an array of two-word entries for each item in the matching
  21179. dialog item list. The first word (itemCData) is the length of the entry if the item
  21180. is a control, or it is a word of flags if the item is an editText or statText item.
  21181. The second word (itemCOffset) is an offset from the beginning of the record to the
  21182. color item entry. This color record is used only for controls and text; icons and
  21183. pictures have a different method of describing associated colors. Set the itemCData
  21184. and itemCOffset fields to zero for controls or text without colors or font changes.
  21185.  
  21186. If the item is an editText or statText item, the bits in the itemCData field determine
  21187. which fields of the text style record to use; these bit equates are listed in the
  21188. following table.
  21189.  
  21190.   Bit    Meaning
  21191.   0      Change the font family
  21192.   1      Change the font face
  21193.   2      Change the font size
  21194.   3      Change the font forecolor
  21195.   4      Add the font size
  21196.   13     Change the font backcolor
  21197.   14     Change the font mode
  21198.   15     The font field is an offset to the name.
  21199.  
  21200. Note:  Multiple text items can share the same font name.
  21201.  
  21202. _______________________________________________________________________________
  21203.  
  21204. The itemCData field for text items contains a superset of the flags passed as the
  21205. mode word to the TextEdit routine TESetStyle.  The constants defined for that routine
  21206. include:
  21207.  
  21208. CONST
  21209.  
  21210.   { Constants for TextEdit and dialog boxes }
  21211.  
  21212.   TEdoFont    = 1;      {set font (family) number}
  21213.   TEdoFace    = 2;      {set character style}
  21214.   TEdoSize    = 4;      {set type size}
  21215.   TEdoColor   = 8;      {set foreground color}
  21216.   TEdoAll     = 15;     {set all attributes}
  21217.   TEaddSize   = 16;     {adjust type size}
  21218.  
  21219.   { Constants for dialog boxes only }
  21220.  
  21221.   doBColor    = 8192;   {set backgound color}
  21222.   doMode      = 16384;  {set txMode}
  21223.   doFontName  = 32768;  {set txFont from name}
  21224.  
  21225. The text style record indicated by itemCOffset must be 20 bytes long, as shown in
  21226. Figure 7. Multiple statText and editText items can use the same text style record. To
  21227. display text in the standard font, color, size, and style, set the itemCData and
  21228. itemCOffset to zero. Allocate space for all fields in the style table, even if they
  21229. are not used. Even if only the first few items of the dialog box have color style
  21230. information, there must be room for all of the items actually in the box (with the
  21231. data and offset words of the unused entries set to zero).
  21232.  
  21233. For controls, the colors are described by a color table identical to the contents of
  21234. a 'cctb' resource used by a GetNewCControl call.  Multiple controls can use the same
  21235. color table. To display a control in the default colors, set the itemCData and itemCOffset
  21236. fields to zero.  The length of the control color table should be the header size of
  21237. eight bytes plus the eight-byte ColorSpec record for each entry in the color table.
  21238.  
  21239. The doFontName array is optional. However, it’s important to point to the name of the
  21240. font instead of just including the font number.  Fonts may be renumbered by font
  21241. installers like the Font/DA Mover as the fonts are moved, so it is safest to rely on
  21242. getting the right font by referring to the name.
  21243.  
  21244. •••Refer to Figure 8.•••
  21245.  
  21246. Figure 8–Sample Dialog with Color Dialog Items (Color Version).
  21247.  
  21248. •••Refer to Figure 9.•••
  21249.  
  21250. Figure 9–Sample Dialog with Color Dialog Items (B/W Version).
  21251.  
  21252. _______________________________________________________________________________
  21253.  
  21254.  
  21255. æKY Using…Color…Dialogs…and…Alerts
  21256. æC »USING COLOR DIALOGS AND ALERTS                              DialogManager
  21257. _______________________________________________________________________________
  21258.  
  21259. The dialog box shown in Figure 8 contains 12 different dialog items. Some of these
  21260. items—the OK and Cancel buttons, the radio buttons and the check box, and the editText
  21261. and statText items—contain color information. The table shown in the figure contains
  21262. the hexadecimal description of the dialog items.  PicItems, iconItems, resCtrls and
  21263. userItems should have zeroed entries for both fields.  All items in the dialog should
  21264. have a field, whether or not the item uses the new features.
  21265.  
  21266. Your application can create a dialog or alert, with color dialog items, within a
  21267. resource file, and then use the GetNewDialog routine with the dialog’s resource ID.
  21268. You can also use the NewCDialog routine to create a dialog or alert within an application,
  21269. passing a handle to the dialog’s item list.
  21270.  
  21271. _______________________________________________________________________________
  21272.  
  21273.  
  21274. æKY Dialog…Records
  21275. æC »DIALOG RECORDS                                              DialogManager
  21276. _______________________________________________________________________________
  21277.  
  21278. To create a dialog, you pass information to the Dialog Manager in a dialog template
  21279. and in individual parameters, or only in parameters; in either case, the Dialog
  21280. Manager incorporates the information into a dialog record. The dialog record contains
  21281. the window record for the dialog window, a handle to the dialog’s item list, and some
  21282. additional fields. The Dialog Manager creates the dialog window by calling the Window
  21283. Manager function NewWindow and then setting the window class in the window record to
  21284. indicate that it’s a dialog window. The routine that creates the dialog returns a
  21285. pointer to the dialog record, which you use thereafter to refer to the dialog in
  21286. Dialog Manager routines or even in Window Manager or QuickDraw routines (see “Dialog
  21287. Pointers” below). The Dialog Manager provides routines for handling events in the
  21288. dialog window and disposing of the dialog when you’re done.
  21289.  
  21290. The data type for a dialog record is called DialogRecord. You can do all the necessary
  21291. operations on a dialog without accessing the fields of the dialog record directly;
  21292. for advanced programmers, however, the exact structure of a dialog record is given
  21293. under “The DialogRecord Data Type” below.
  21294.  
  21295. _______________________________________________________________________________
  21296.  
  21297. »Dialog Pointers
  21298.  
  21299. There are two types of dialog pointer, DialogPtr and DialogPeek, analogous to the
  21300. window pointer types WindowPtr and WindowPeek. Most programmers will only need to use
  21301. DialogPtr.
  21302.  
  21303. The Dialog Manager defines the following type of dialog pointer:
  21304.  
  21305. TYPE  DialogPtr = WindowPtr;
  21306.  
  21307. It can do this because the first field of a dialog record contains the window record
  21308. for the dialog window. This type of pointer can be used to access fields of the
  21309. window record or can be passed to Window Manager routines that expect window pointers
  21310. as parameters. Since the WindowPtr data type is itself defined as GrafPtr, this type
  21311. of dialog pointer can also be used to access fields of the dialog window’s grafPort
  21312. or passed to QuickDraw routines that expect pointers to grafPorts as parameters.
  21313.  
  21314. For programmers who want to access dialog record fields beyond the window record, the
  21315. Dialog Manager also defines the following type of dialog pointer:
  21316.  
  21317. TYPE  DialogPeek = ^DialogRecord;
  21318.  
  21319. Assembly-language note:  From assembly language, of course, there’s no
  21320.                          type checking on pointers, and the two types
  21321.                          of pointer are equal.
  21322.  
  21323. _______________________________________________________________________________
  21324.  
  21325. »The DialogRecord Data Type
  21326.  
  21327. For those who want to know more about the data structure of a dialog record, the
  21328. exact structure is given here.
  21329.  
  21330. TYPE  DialogRecord = RECORD
  21331.                        window:     WindowRecord;  {dialog window}
  21332.                        items:      Handle;        {item list}
  21333.                        textH:      TEHandle;      {current editText item}
  21334.                        editField:  INTEGER;       {editText item number minus 1}
  21335.                        editOpen:   INTEGER;       {used internally}
  21336.                        aDefItem:   INTEGER        {default button item number}
  21337.                      END;
  21338.  
  21339. The window field contains the window record for the dialog window. The items field
  21340. contains a handle to the item list used for the dialog. (Remember that after reading
  21341. an item list from a resource file, the Dialog Manager makes a copy of it and uses
  21342. that copy.)
  21343.  
  21344. Note:  To get or change information about an item in a dialog, you pass the
  21345.        dialog pointer and the item number to a Dialog Manager procedure.
  21346.        You’ll never access information directly through the handle to the
  21347.        item list.
  21348.  
  21349. The Dialog Manager uses the next three fields when there are one or more editText
  21350. items in the dialog. If there’s more than one such item, these fields apply to the
  21351. one that currently is selected or displays the insertion point. The textH field
  21352. contains the handle to the edit record used by TextEdit. EditField is 1 less than the
  21353. item number of the current editText item, or –1 if there’s no editText item in the
  21354. dialog. The editOpen field is used internally by the Dialog Manager.
  21355.  
  21356. Note:  Actually, a single edit record is shared by all editText items; any
  21357.        changes you make to it will apply to all such items. See the TextEdit
  21358.        chapter for details about what kinds of changes you can make.
  21359.  
  21360. The aDefItem field is used for modal dialogs and alerts, which are treated internally
  21361. as special modal dialogs. It contains the item number of the default button. The
  21362. default button for a modal dialog is the first item in the item list, so this field
  21363. contains 1 for modal dialogs. The default button for an alert is specified in the
  21364. alert template; see the following section for more information.
  21365.  
  21366. _______________________________________________________________________________
  21367.  
  21368.  
  21369. æKY Alerts
  21370. æC »ALERTS                                                      DialogManager
  21371. _______________________________________________________________________________
  21372.  
  21373. When you call a Dialog Manager routine to invoke an alert, you pass it the resource
  21374. ID of the alert template, which contains the following:
  21375.  
  21376.   •  A rectangle, given in global coordinates, which determines the alert
  21377.      window’s size and location. It becomes the portRect of the window’s
  21378.      grafPort. To allow for the menu bar and the border around the portRect,
  21379.      the top coordinate of the rectangle should be at least 25 points below
  21380.      the top of the screen.
  21381.   •  The resource ID of the item list for the alert.
  21382.   •  Information about exactly what should happen at each stage of the alert.
  21383.  
  21384. Every alert has four stages, corresponding to consecutive occurrences of the alert: 
  21385. The first three stages correspond to the first three occurrences, while the fourth
  21386. stage includes the fourth occurrence and any beyond the fourth. (The Dialog Manager
  21387. compares the current alert’s resource ID to the last alert’s resource ID to determine
  21388. whether it’s the same alert.) The actions for each stage are specified by the following
  21389. three pieces of information:
  21390.  
  21391.   •  which is the default button—the OK button (or, if none, a button that
  21392.      will perform the command) or the Cancel button
  21393.   •  whether the alert box is to be drawn
  21394.   •  which of four sounds should be emitted at this stage of the alert
  21395.  
  21396. The alert sounds are determined by a sound procedure that emits one of up to four
  21397. tones or sequences of tones. The sound procedure has one parameter, an integer from 0
  21398. to 3; it can emit any sound for each of these numbers, which identify the sounds in
  21399. the alert template. For example, you might declare a sound procedure named MySound as
  21400. follows:
  21401.  
  21402. PROCEDURE MySound (soundNo:  INTEGER);
  21403.  
  21404. If you don’t write your own sound procedure, the Dialog Manager uses the standard
  21405. one:  Sound number 0 represents no sound and sound numbers 1 through 3 represent the
  21406. corresponding number of short beeps, each of the same pitch and duration. The volume
  21407. of each beep depends on the current speaker volume setting, which the user can adjust
  21408. with the Control Panel desk accessory. If the user has set the speaker volume to 0,
  21409. the menu bar will blink in place of each beep.
  21410.  
  21411. For example, if the second stage of an alert is to cause a beep and no alert box, you
  21412. can just specify the following for that stage in the alert template:  Don’t draw the
  21413. alert box, and use sound number 1. If instead you want, say, two successive beeps of
  21414. different pitch, you need to write a procedure that will emit that sound for a particular
  21415. sound number, and specify that number in the alert template. The Macintosh Operating
  21416. System includes routines for emitting sound; see the Sound Driver chapter, and also
  21417. the simple SysBeep procedure in the Operating System Utilties chapter. (The standard
  21418. sound procedure calls SysBeep.)
  21419.  
  21420. Note:  When the Dialog Manager detects a click outside an alert box or a
  21421.        modal dialog box, it emits sound number 1; thus, for consistency
  21422.        with the Macintosh User Interface Guidelines, sound number 1 should
  21423.        always be a single beep.
  21424.  
  21425. Internally, alerts are treated as special modal dialogs. The alert routine creates
  21426. the alert window by calling NewDialog. The Dialog Manager works from the dialog
  21427. record created by NewDialog, just as when it operates on a dialog window, but it
  21428. disposes of the window before returning to the application. Normally your application
  21429. won’t access the dialog record for an alert; however, there is a way that this can
  21430. happen:  For any alert, you can specify a procedure that will be executed repeatedly
  21431. during the alert, and this procedure may access the dialog record. For details, see
  21432. the alert routines under
  21433. “Invoking Alerts” in the “Dialog Manager Routines” section.
  21434.  
  21435. _______________________________________________________________________________
  21436.  
  21437.  
  21438. æKY Using…the…Dialog…Manager
  21439. æC »USING THE DIALOG MANAGER                                    DialogManager
  21440. _______________________________________________________________________________
  21441.  
  21442. Before using the Dialog Manager, you must initialize QuickDraw, the Font Manager, the
  21443. Window Manager, the Menu Manager, and TextEdit, in that order. The first Dialog
  21444. Manager routine to call is InitDialogs, which initializes the Dialog Manager. If you
  21445. want the font in your dialog and alert windows to be other than the system font, call
  21446. SetDAFont to change the font.
  21447.  
  21448. Where appropriate in your program, call NewDialog or GetNewDialog to create any
  21449. dialogs you need. Usually you’ll call GetNewDialog, which takes descriptive information
  21450. about the dialog from a dialog template in a resource file. You can instead pass the
  21451. information in individual parameters to NewDialog. In either case, you can supply a
  21452. pointer to the storage for the dialog record or let it be allocated by the Dialog
  21453. Manager. When you no longer need a dialog, you’ll usually call CloseDialog if you
  21454. supplied the storage, or DisposDialog if not.
  21455.  
  21456. In most cases, you probably won’t have to make any changes to the dialogs from the
  21457. way they’re defined in the resource file. However, if you should want to modify an
  21458. item in a dialog, you can call GetDItem to get the information about the item and
  21459. SetDItem to change it. In particular, SetDItem is the routine to use for installing a
  21460. userItem. In some cases it may be appropriate to call some other Toolbox routine to
  21461. change the item; for example, to change or move a control in a dialog, you would get
  21462. its handle from GetDItem and then call the appropriate Control Manager routine. There
  21463. are also two procedures specifically for accessing or setting the content of a text
  21464. item in a dialog box:  GetIText and SetIText.
  21465.  
  21466. To handle events in a modal dialog, just call the ModalDialog procedure after putting
  21467. up the dialog box. If your application includes any modeless dialog boxes, you’ll
  21468. pass events to IsDialogEvent to learn whether they need to be handled as part of a
  21469. dialog, and then usually call DialogSelect if so. Before calling DialogSelect, however,
  21470. you should check whether the user has given the keyboard equivalent of a command, and
  21471. you may want to check for other special cases, depending on your application. You can
  21472. support the use of the standard editing commands in a modeless dialog’s editText
  21473. items with DlgCut, DlgCopy, DlgPaste, and DlgDelete.
  21474.  
  21475. A dialog box that contains editText items normally comes up with the insertion point
  21476. in the first such item in its item list. You may instead want to bring up a dialog
  21477. box with text selected in an editText item, or to cause an insertion point or text
  21478. selection to reappear after the user has made an error in entering text. For example,
  21479. the user who accidentally types nonnumeric input when a number is required can be
  21480. given the opportunity to type the entry again. The SelIText procedure makes this
  21481. possible.
  21482.  
  21483. For alerts, if you want other sounds besides the standard ones (up to three short
  21484. beeps), write your own sound procedure and call ErrorSound to ma